turn off debug mode, add more docs & examples
This commit is contained in:
parent
1f1b0d7ebc
commit
b4b3c0497a
135
README.md
135
README.md
|
@ -5,11 +5,11 @@ Automatic [Let's Encrypt](https://lettsencrypt.org) HTTPS Certificates for node.
|
||||||
|
|
||||||
* Automatic HTTPS with ExpressJS
|
* Automatic HTTPS with ExpressJS
|
||||||
* Automatic live renewal (in-process)
|
* Automatic live renewal (in-process)
|
||||||
* safe for use with node's cluster module
|
* On-the-fly HTTPS certificates for Dynamic DNS (in-process, no server restart)
|
||||||
* configurable for automatic registration (in-process)
|
* Works with node cluster out of the box
|
||||||
* usable via commandline as well
|
* usable via commandline as well
|
||||||
* [90-day certificates](https://letsencrypt.org/2015/11/09/why-90-days.html)
|
|
||||||
* Free SSL (HTTPS Certificates for TLS)
|
* Free SSL (HTTPS Certificates for TLS)
|
||||||
|
* [90-day certificates](https://letsencrypt.org/2015/11/09/why-90-days.html)
|
||||||
|
|
||||||
Install
|
Install
|
||||||
=======
|
=======
|
||||||
|
@ -48,15 +48,142 @@ le.register({
|
||||||
**However**, due to the nature of what this library does, it has a few more "moving parts"
|
**However**, due to the nature of what this library does, it has a few more "moving parts"
|
||||||
than what makes sense to show in a minimal snippet.
|
than what makes sense to show in a minimal snippet.
|
||||||
|
|
||||||
|
### One Time Registration
|
||||||
|
|
||||||
* [commandline (standalone with "webroot")](https://github.com/Daplie/node-letsencrypt/blob/master/examples/commandline.js)
|
* [commandline (standalone with "webroot")](https://github.com/Daplie/node-letsencrypt/blob/master/examples/commandline.js)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var LE = require('letsencrypt');
|
||||||
|
var config = require('./config-minimal');
|
||||||
|
|
||||||
|
// Note: you should make this special dir in your product and leave it empty
|
||||||
|
config.le.webrootPath = __dirname + '/../tests/acme-challenge';
|
||||||
|
config.le.server = LE.stagingServer;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Manual Registration
|
||||||
|
//
|
||||||
|
var le = LE.create(config.backend, config.le);
|
||||||
|
le.register({
|
||||||
|
agreeTos: true
|
||||||
|
, domains: ['example.com'] // CHANGE TO YOUR DOMAIN
|
||||||
|
, email: 'user@email.com' // CHANGE TO YOUR EMAIL
|
||||||
|
}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.error('[Error]: node-letsencrypt/examples/standalone');
|
||||||
|
console.error(err.stack);
|
||||||
|
} else {
|
||||||
|
console.log('success');
|
||||||
|
}
|
||||||
|
|
||||||
|
plainServer.close();
|
||||||
|
tlsServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Express App
|
||||||
|
//
|
||||||
|
var app = require('express')();
|
||||||
|
app.use('/', le.middleware());
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// HTTP & HTTPS servers
|
||||||
|
// (required for domain validation)
|
||||||
|
//
|
||||||
|
var plainServer = require('http').createServer(app).listen(config.plainPort, function () {
|
||||||
|
console.log('Listening http', this.address());
|
||||||
|
});
|
||||||
|
|
||||||
|
var tlsServer = require('https').createServer({
|
||||||
|
key: config.tlsKey
|
||||||
|
, cert: config.tlsCert
|
||||||
|
, SNICallback: le.sniCallback
|
||||||
|
}, app).listen(config.tlsPort, function () {
|
||||||
|
console.log('Listening http', this.address());
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# manual standalone registration via commandline
|
# manual standalone registration via commandline
|
||||||
# (runs against testing server on tls port 5001)
|
# (runs against testing server on tls port 5001)
|
||||||
node examples/commandline.js example.com,www.example.com user@example.net agree
|
node examples/commandline.js example.com,www.example.com user@example.net agree
|
||||||
```
|
```
|
||||||
|
|
||||||
* [expressjs (fully automatic https)](https://github.com/Daplie/node-letsencrypt/blob/master/examples/express.js)
|
### Express
|
||||||
|
|
||||||
|
Fully Automatic HTTPS with ExpressJS using Free SSL certificates from Let's Encrypt
|
||||||
|
|
||||||
|
* [Minimal ExpressJS Example](https://github.com/Daplie/node-letsencrypt/blob/master/examples/express-minimal.js)
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var LE = require('letsencrypt');
|
||||||
|
var config = require('./config-minimal');
|
||||||
|
|
||||||
|
// Note: you should make this special dir in your product and leave it empty
|
||||||
|
config.le.webrootPath = __dirname + '/../tests/acme-challenge';
|
||||||
|
config.le.server = LE.stagingServer;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Automatically Register / Renew Domains
|
||||||
|
//
|
||||||
|
var le = LE.create(config.backend, config.le, {
|
||||||
|
sniRegisterCallback: function (args, expiredCert, cb) {
|
||||||
|
// Security: check that this is actually a subdomain we allow
|
||||||
|
// (otherwise an attacker can cause you to rate limit against the LE server)
|
||||||
|
|
||||||
|
var hostname = args.domains[0];
|
||||||
|
if (!/\.example\.com$/.test(hostname)) {
|
||||||
|
console.error("bad domain '" + hostname + "', not a subdomain of example.com");
|
||||||
|
cb(nul, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// agree to the LE TOS for this domain
|
||||||
|
args.agreeTos = true;
|
||||||
|
args.email = 'user@example.com';
|
||||||
|
|
||||||
|
// use the cert even though it's expired
|
||||||
|
if (expiredCert) {
|
||||||
|
cb(null, expiredCert);
|
||||||
|
cb = function () { /*ignore*/ };
|
||||||
|
}
|
||||||
|
|
||||||
|
// register / renew the certificate in the background
|
||||||
|
le.register(args, function () {});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Express App
|
||||||
|
//
|
||||||
|
var app = require('express')();
|
||||||
|
app.use('/', le.middleware());
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// HTTP & HTTPS servers
|
||||||
|
//
|
||||||
|
require('http').createServer(app).listen(config.plainPort, function () {
|
||||||
|
console.log('Listening http', this.address());
|
||||||
|
});
|
||||||
|
|
||||||
|
require('https').createServer({
|
||||||
|
key: config.tlsKey
|
||||||
|
, cert: config.tlsCert
|
||||||
|
, SNICallback: le.sniCallback
|
||||||
|
}, app).listen(config.tlsPort, function () {
|
||||||
|
console.log('Listening http', this.address());
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
* [Full ExpressJS Example](https://github.com/Daplie/node-letsencrypt/blob/master/examples/express.js)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# clear out the certificates
|
# clear out the certificates
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
var PromiseA = require('bluebird');
|
var PromiseA = require('bluebird');
|
||||||
var fs = PromiseA.promisifyAll(require('fs'));
|
var fs = PromiseA.promisifyAll(require('fs'));
|
||||||
|
|
||||||
module.exports.create = function (leBinPath, defaults) {
|
module.exports.create = function (leBinPath, defaults, opts) {
|
||||||
defaults.webroot = true; // standalone should not be set to true
|
defaults.webroot = true;
|
||||||
defaults.renewByDefault = true;
|
defaults.renewByDefault = true;
|
||||||
defaults.text = true;
|
defaults.text = true;
|
||||||
|
|
||||||
var LEP = require('letsencrypt-python');
|
var LEP = require('letsencrypt-python');
|
||||||
var lep = PromiseA.promisifyAll(LEP.create(leBinPath, { debug: true }));
|
var lep = PromiseA.promisifyAll(LEP.create(leBinPath, opts));
|
||||||
var wrapped = {
|
var wrapped = {
|
||||||
registerAsync: function (args) {
|
registerAsync: function (args) {
|
||||||
return lep.registerAsync('certonly', args);
|
return lep.registerAsync('certonly', args);
|
||||||
|
@ -28,7 +28,7 @@ module.exports.create = function (leBinPath, defaults) {
|
||||||
return {
|
return {
|
||||||
key: arr[0] // privkey.pem
|
key: arr[0] // privkey.pem
|
||||||
, cert: arr[1] // fullchain.pem
|
, cert: arr[1] // fullchain.pem
|
||||||
// TODO parse centificate
|
// TODO parse centificate for lifetime / expiresAt
|
||||||
, issuedAt: arr[2].mtime.valueOf()
|
, issuedAt: arr[2].mtime.valueOf()
|
||||||
};
|
};
|
||||||
}, function () {
|
}, function () {
|
||||||
|
@ -38,4 +38,4 @@ module.exports.create = function (leBinPath, defaults) {
|
||||||
};
|
};
|
||||||
|
|
||||||
return wrapped;
|
return wrapped;
|
||||||
}
|
};
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var LE = require('../');
|
||||||
|
var config = require('./config-minimal');
|
||||||
|
|
||||||
|
// Note: you should make this special dir in your product and leave it empty
|
||||||
|
config.le.webrootPath = __dirname + '/../tests/acme-challenge';
|
||||||
|
config.le.server = LE.stagingServer;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Manual Registration
|
||||||
|
//
|
||||||
|
var le = LE.create(config.backend, config.le);
|
||||||
|
le.register({
|
||||||
|
agreeTos: true
|
||||||
|
, domains: ['example.com'] // CHANGE TO YOUR DOMAIN
|
||||||
|
, email: 'user@example.com' // CHANGE TO YOUR EMAIL
|
||||||
|
}, function (err) {
|
||||||
|
if (err) {
|
||||||
|
console.error('[Error]: node-letsencrypt/examples/standalone');
|
||||||
|
console.error(err.stack);
|
||||||
|
} else {
|
||||||
|
console.log('success');
|
||||||
|
}
|
||||||
|
|
||||||
|
plainServer.close();
|
||||||
|
tlsServer.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Express App
|
||||||
|
//
|
||||||
|
var app = require('express')();
|
||||||
|
app.use('/', le.middleware());
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// HTTP & HTTPS servers
|
||||||
|
// (required for domain validation)
|
||||||
|
//
|
||||||
|
var plainServer = require('http').createServer(app).listen(config.plainPort, function () {
|
||||||
|
console.log('Listening http', this.address());
|
||||||
|
});
|
||||||
|
|
||||||
|
var tlsServer = require('https').createServer({
|
||||||
|
key: config.tlsKey
|
||||||
|
, cert: config.tlsCert
|
||||||
|
, SNICallback: le.sniCallback
|
||||||
|
}, app).listen(config.tlsPort, function () {
|
||||||
|
console.log('Listening http', this.address());
|
||||||
|
});
|
|
@ -29,7 +29,7 @@ var bkDefaults = {
|
||||||
, text: true
|
, text: true
|
||||||
};
|
};
|
||||||
|
|
||||||
var leBinPath = require('homedir')() + '/.local/share/letsencrypt/bin/letsencrypt';
|
var leBinPath = require('os').homedir() + '/.local/share/letsencrypt/bin/letsencrypt';
|
||||||
var LEB = require('../backends-python');
|
var LEB = require('../backends-python');
|
||||||
var backend = LEB.create(leBinPath, bkDefaults, { debug: true });
|
var backend = LEB.create(leBinPath, bkDefaults, { debug: true });
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
var binpath = require('os').homedir() + '/.local/share/letsencrypt/bin/letsencrypt';
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
|
||||||
|
plainPort: 80
|
||||||
|
, tlsPort: 5001 // 5001 for testing, normally 443
|
||||||
|
, tlsKey: require('localhost.daplie.com-certificates').key
|
||||||
|
, tlsCert: require('localhost.daplie.com-certificates').cert
|
||||||
|
|
||||||
|
|
||||||
|
, le: {
|
||||||
|
webrootPath: path.join(__dirname, '..', 'tests', 'acme-challenge')
|
||||||
|
, fullchainTpl: '/live/:hostname/fullchain.pem'
|
||||||
|
, privkeyTpl: '/live/:hostname/privkey.pem'
|
||||||
|
, configDir: path.join(__dirname, '..', 'tests', 'letsencrypt.config')
|
||||||
|
|
||||||
|
// these are specific to the python client and won't be needed with the purejs library
|
||||||
|
, logsDir: path.join(__dirname, '..', 'tests', 'letsencrypt.logs')
|
||||||
|
, workDir: path.join(__dirname, '..', 'tests', 'letsencrypt.work')
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//config.backend = require('letsencrypt/backends-python').create(binpath, config.le);
|
||||||
|
config.backend = require('../backends-python').create(binpath, config.le);
|
||||||
|
|
||||||
|
module.exports = config;
|
|
@ -0,0 +1,57 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var LE = require('../');
|
||||||
|
var config = require('./config-minimal');
|
||||||
|
|
||||||
|
// Note: you should make this special dir in your product and leave it empty
|
||||||
|
config.le.webrootPath = __dirname + '/../tests/acme-challenge';
|
||||||
|
config.le.server = LE.stagingServer;
|
||||||
|
|
||||||
|
var le = LE.create(config.backend, config.le, {
|
||||||
|
sniRegisterCallback: function (args, expiredCert, cb) {
|
||||||
|
// In theory you should never get an expired certificate because
|
||||||
|
// the certificates automatically renew in the background starting
|
||||||
|
// about a week before they expire.
|
||||||
|
// (the default behavior is to randomly stagger renewals)
|
||||||
|
// so in this case we'll just return the expired certificate
|
||||||
|
if (expiredCert) { return cb(null, expiredCert); }
|
||||||
|
|
||||||
|
// If we get here that means this domain hasn't been registered yet
|
||||||
|
// Security Warning: you should either manually register domains
|
||||||
|
// and return null here or check that the sni header isn't being
|
||||||
|
// spoofed and this is actually a domain you own before registering
|
||||||
|
//
|
||||||
|
// cb(null, null);
|
||||||
|
|
||||||
|
var hostname = args.domains[0];
|
||||||
|
console.log("[TODO] check that '" + hostname + "' is one I expect");
|
||||||
|
|
||||||
|
args.agreeTos = true;
|
||||||
|
args.email = 'user@example.com';
|
||||||
|
|
||||||
|
le.register(args, cb);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Express App
|
||||||
|
//
|
||||||
|
var app = require('express')();
|
||||||
|
app.use('/', le.middleware());
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// HTTP & HTTPS servers
|
||||||
|
//
|
||||||
|
require('http').createServer(app).listen(config.plainPort, function () {
|
||||||
|
console.log('Listening http', this.address());
|
||||||
|
});
|
||||||
|
|
||||||
|
require('https').createServer({
|
||||||
|
key: config.tlsKey
|
||||||
|
, cert: config.tlsCert
|
||||||
|
, SNICallback: le.sniCallback
|
||||||
|
}, app).listen(config.tlsPort, function () {
|
||||||
|
console.log('Listening http', this.address());
|
||||||
|
});
|
|
@ -28,7 +28,7 @@ var bkDefaults = {
|
||||||
, server: LE.stagingServer
|
, server: LE.stagingServer
|
||||||
};
|
};
|
||||||
|
|
||||||
var leBinPath = require('homedir')() + '/.local/share/letsencrypt/bin/letsencrypt';
|
var leBinPath = require('os').homedir() + '/.local/share/letsencrypt/bin/letsencrypt';
|
||||||
var LEB = require('../backends-python');
|
var LEB = require('../backends-python');
|
||||||
var backend = LEB.create(leBinPath, bkDefaults, { debug: true });
|
var backend = LEB.create(leBinPath, bkDefaults, { debug: true });
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue