diff --git a/README.md b/README.md index c14ba7c..7dde8b2 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,11 @@ letsencrypt Let's Encrypt for node.js -This enables you to get Free SSL Certificates for Automatic HTTPS. - -#### NOT YET PUBLISHED - -* Dec 12 2015: gettin' really close -* Dec 11 2015: almost done (node-letsencrypt-python complete) -* Dec 10 2015: began tinkering + * Automatic HTTPS with Express + * Automatic renewal (in-process) + * safe for use with node cluster + * configurable for automatic registration (in-process) + * usable via commandline as well Install ======= @@ -49,6 +47,19 @@ le.register({ than what makes sense to show in a minimal snippet. * [commandline (standalone with "webroot")](https://github.com/Daplie/node-letsencrypt/blob/master/examples/commandline.js) + +```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 +``` + +```bash +# automatic registration and renewal (certs install as you visit the site for the first time) +# (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) ### non-root diff --git a/backends-python.js b/backends-python.js index f5eb43d..ccd2f6c 100644 --- a/backends-python.js +++ b/backends-python.js @@ -4,8 +4,9 @@ var PromiseA = require('bluebird'); var fs = PromiseA.promisifyAll(require('fs')); module.exports.create = function (leBinPath, defaults) { - defaults.webroot = true; + defaults.webroot = true; // standalone should not be set to true defaults.renewByDefault = true; + defaults.text = true; var LEP = require('letsencrypt-python'); var lep = PromiseA.promisifyAll(LEP.create(leBinPath, { debug: true })); diff --git a/examples/express.js b/examples/express.js new file mode 100644 index 0000000..30c52ad --- /dev/null +++ b/examples/express.js @@ -0,0 +1,93 @@ +'use strict'; + +var conf = { + domains: (process.argv[2]||'').split(',') +, email: process.argv[3] +, agree: 'agree' === process.argv[4] +}; +var port = 80; +var tlsPort = 5001; + +if (!conf.domains || !conf.email || !conf.agree) { + console.error("Usage: node examples/express agree"); + console.error("Example: node examples/express example.com,www.example.com user@example.com agree"); + return; +} + +var LE = require('../'); +var path = require('path'); +// backend-specific defaults will be passed through +// Note: Since agreeTos is a legal agreement, I would suggest not accepting it by default +var bkDefaults = { + webrootPath: path.join(__dirname, '..', 'tests', 'acme-challenge') +, fullchainTpl: '/live/:hostname/fullchain.pem' +, privkeyTpl: '/live/:hostname/privkey.pem' +, configDir: path.join(__dirname, '..', 'tests', 'letsencrypt.config') +, logsDir: path.join(__dirname, '..', 'tests', 'letsencrypt.logs') +, workDir: path.join(__dirname, '..', 'tests', 'letsencrypt.work') +, server: LE.stagingServer +}; + +var leBinPath = require('homedir')() + '/.local/share/letsencrypt/bin/letsencrypt'; +var LEB = require('../backends-python'); +var backend = LEB.create(leBinPath, bkDefaults, { debug: true }); + +var le = LE.create(backend, bkDefaults, { + sniRegisterCallback: function (args, certInfo, cb) { + var allowedDomains = conf.domains; // require('../tests/config').allowedDomains; + + // let the renewal take place in the background + if (certInfo && certInfo.context) { + cb(null, certInfo); + return; + } + + // verify that these are domains we allow to register on our server + if (args.domains.length && args.domains.every(function (hostname) { + hostname = hostname.toLowerCase(); + return (-1 !== allowedDomains.indexOf(hostname)); + })) { + // wait for registration before responding + args.agreeTos = conf.agree; + args.email = conf.email; // you'd want to lookup which user has this email + le.register(args, cb); + } else { + // I don't know where this error goes (SNICallback)... but at least we put it somewhere + cb(new Error("SNI came in for (an) unrecognized domain(s): '" + args.domains + "'")); + } + } +/* +, setChallenge: function (hostnames, key, value, cb) { + // the python backend needs fs.watch implemented + // before this would work (and even then it would be difficult) + } +, getChallenge: function (hostnames, key, cb) { + // + } +, registrationFailureCallback: function (args, certInfo, cb) { + what do to when a backgrounded registration fails + } +*/ +}); + +var localCerts = require('localhost.daplie.com-certificates'); +var express = require('express'); +var app = express(); + +app.use('/', le.middleware()); + +var server = require('http').createServer(); +server.on('request', app); +server.listen(port, function () { + console.log('Listening http', server.address()); +}); + +var tlsServer = require('https').createServer({ + key: localCerts.key +, cert: localCerts.cert +, SNICallback: le.sniCallback +}); +tlsServer.on('request', app); +tlsServer.listen(tlsPort, function () { + console.log('Listening http', tlsServer.address()); +}); diff --git a/tests/config.js b/tests/config.js index 1acc050..6cab74b 100644 --- a/tests/config.js +++ b/tests/config.js @@ -10,4 +10,5 @@ module.exports = { , configDir: path.join(__dirname, "letsencrypt.config") , workDir: path.join(__dirname, "letsencrypt.work") , logsDir: path.join(__dirname, "letsencrypt.logs") +, allowedDomains: ['example.com'] };