turn off debug mode, add more docs & examples

This commit is contained in:
AJ ONeal 2015-12-13 08:05:24 +00:00
parent 1f1b0d7ebc
commit b4b3c0497a
7 changed files with 279 additions and 11 deletions

135
README.md
View File

@ -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

View File

@ -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;
} };

View File

@ -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());
});

View File

@ -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 });

View File

@ -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;

View File

@ -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());
});

View File

@ -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 });