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 live renewal (in-process)
|
||||
* safe for use with node's cluster module
|
||||
* configurable for automatic registration (in-process)
|
||||
* On-the-fly HTTPS certificates for Dynamic DNS (in-process, no server restart)
|
||||
* Works with node cluster out of the box
|
||||
* usable via commandline as well
|
||||
* [90-day certificates](https://letsencrypt.org/2015/11/09/why-90-days.html)
|
||||
* Free SSL (HTTPS Certificates for TLS)
|
||||
* [90-day certificates](https://letsencrypt.org/2015/11/09/why-90-days.html)
|
||||
|
||||
Install
|
||||
=======
|
||||
|
@ -48,15 +48,142 @@ le.register({
|
|||
**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.
|
||||
|
||||
### One Time Registration
|
||||
|
||||
* [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
|
||||
# manual standalone registration via commandline
|
||||
# (runs against testing server on tls port 5001)
|
||||
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
|
||||
# clear out the certificates
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
var PromiseA = require('bluebird');
|
||||
var fs = PromiseA.promisifyAll(require('fs'));
|
||||
|
||||
module.exports.create = function (leBinPath, defaults) {
|
||||
defaults.webroot = true; // standalone should not be set to true
|
||||
module.exports.create = function (leBinPath, defaults, opts) {
|
||||
defaults.webroot = true;
|
||||
defaults.renewByDefault = true;
|
||||
defaults.text = true;
|
||||
|
||||
var LEP = require('letsencrypt-python');
|
||||
var lep = PromiseA.promisifyAll(LEP.create(leBinPath, { debug: true }));
|
||||
var lep = PromiseA.promisifyAll(LEP.create(leBinPath, opts));
|
||||
var wrapped = {
|
||||
registerAsync: function (args) {
|
||||
return lep.registerAsync('certonly', args);
|
||||
|
@ -28,7 +28,7 @@ module.exports.create = function (leBinPath, defaults) {
|
|||
return {
|
||||
key: arr[0] // privkey.pem
|
||||
, cert: arr[1] // fullchain.pem
|
||||
// TODO parse centificate
|
||||
// TODO parse centificate for lifetime / expiresAt
|
||||
, issuedAt: arr[2].mtime.valueOf()
|
||||
};
|
||||
}, function () {
|
||||
|
@ -38,4 +38,4 @@ module.exports.create = function (leBinPath, defaults) {
|
|||
};
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
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 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
|
||||
};
|
||||
|
||||
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 backend = LEB.create(leBinPath, bkDefaults, { debug: true });
|
||||
|
||||
|
|
Loading…
Reference in New Issue