diff --git a/README.md b/README.md index 6c4ef38..fe13e5b 100644 --- a/README.md +++ b/README.md @@ -1,79 +1,263 @@ -| Sponsored by [ppl](https://ppl.family) -| [acme-v2.js](https://git.coolaj86.com/coolaj86/acme-v2.js) -| **greenlock** ([npm](https://www.npmjs.com/package/greenlock)) -| [greenlock-cli](https://git.coolaj86.com/coolaj86/greenlock-cli.js) -| [greenlock-express](https://git.coolaj86.com/coolaj86/greenlock-express.js) - ([koa](https://git.coolaj86.com/coolaj86/greenlock-koa.js)) - ([hapi](https://git.coolaj86.com/coolaj86/greenlock-hapi.js)) -| [greenlock-cluster](https://git.coolaj86.com/coolaj86/greenlock-cluster.js) -| - -Greenlock™ for node.js +🔐 Greenlock™ for node.js ===== -(previously node-letsencrypt) -Automatic [Let's Encrypt](https://letsencrypt.org) (ACME) HTTPS / TLS / SSL Certificates for node.js +Greenlock provides Free SSL, Free Wildcard SSL, and Fully Automated HTTPS
+certificates issued by Let's Encrypt v2 via [ACME](https://git.coolaj86.com/coolaj86/acme-v2.js) -Free SSL with [90-day](https://letsencrypt.org/2015/11/09/why-90-days.html) HTTPS / TLS Certificates +| Sponsored by [ppl](https://ppl.family) | +Greenlock works +in the [Commandline](https://git.coolaj86.com/coolaj86/greenlock-cli.js) (cli), +as a [Web Server](https://git.coolaj86.com/coolaj86/greenlock-server.js), +in [Web Browsers](https://git.coolaj86.com/coolaj86/greenlock.html) (WebCrypto), +and with **node.js** ([npm](https://www.npmjs.com/package/greenlock)). -Are these the droids you're looking for? +Features +======== + + - [x] Actively Maintained and Supported + - [x] Automatic HTTPS + - [x] Free SSL + - [x] Free Wildcard SSL + - [x] Multiple domain support (up to 100 altnames per SAN) + - [x] Dynamic Virtual Hosting (vhost) + - [x] Automatical renewal (10 to 14 days before expiration) + - [x] Great ACME support via [acme.js](https://git.coolaj86.com/coolaj86/acme-v2.js) + - [x] ACME draft 11 + - [x] Let's Encrypt v2 + - [x] Let's Encrypt v1 + - [x] [Commandline](https://git.coolaj86.com/coolaj86/greenlock-cli.js) (cli) Utilities + - [x] Works with `bash`, `fish`, `zsh`, `cmd.exe`, `PowerShell`, and more + - [x] [Browser](https://git.coolaj86.com/coolaj86/greenlock.html) (cli) Support + - [x] Full node.js support, with modules for + - [x] [http/https](https://git.coolaj86.com/coolaj86/greenlock-express.js/src/branch/master/examples/https-server.js) (native core modules) + - [x] [Express.js](https://git.coolaj86.com/coolaj86/greenlock-express.js) + - [x] [cluster](https://git.coolaj86.com/coolaj86/greenlock-cluster.js) + - [x] [hapi](https://git.coolaj86.com/coolaj86/greenlock-hapi.js) + - [x] [Koa](https://git.coolaj86.com/coolaj86/greenlock-koa.js) + - [x] [rill](https://git.coolaj86.com/coolaj86/greenlock-rill.js) + - [x] also works with `spdy`, `restify`, and all other node http and middleware systems + - [x] Great for securing your Raspberry Pi + - [x] Extensible Plugin Support + - [x] AWS (S3, Route53) + - [x] Azure + - [x] CloudFlare + - [x] Consul + - [x] Digital Ocean + - [x] etcd + - [x] Redis + +Greenlock.js for Middleware ------ -This is a **low-level library** for implementing ACME / LetsEncrypt Clients, CLIs, -system tools, and abstracting storage backends (file vs db, etc). +Documentation for using Greenlock with +[http/https](https://git.coolaj86.com/coolaj86/greenlock-express.js/src/branch/master/examples/https-server.js), +[Express.js](https://git.coolaj86.com/coolaj86/greenlock-express.js), +[cluster](https://git.coolaj86.com/coolaj86/greenlock-cluster.js), +[hapi](https://git.coolaj86.com/coolaj86/greenlock-hapi.js), +[Koa](https://git.coolaj86.com/coolaj86/greenlock-koa.js), +[rill](https://git.coolaj86.com/coolaj86/greenlock-rill.js). +[restify](https://git.coolaj86.com/coolaj86/greenlock-restify.js). -For `express`, raw `https` or `spdy`, or `restify` (same as raw https) see -[**greenlock-express** (previously letsencrypt-express)](https://git.coolaj86.com/coolaj86/greenlock-express.js) and [greenlock-cluster (previously letsencrypt-cluster)](https://git.coolaj86.com/coolaj86/greenlock-cluster.js). +Table of Contents +================= -For `hapi` see [greenlock-hapi (previously letsencrypt-hapi)](https://git.coolaj86.com/coolaj86/greenlock-hapi.js). - -For `koa` or `rill` -see [greenlock-koa (previously letsencrypt-koa)](https://git.coolaj86.com/coolaj86/greenlock-koa.js). - -For `bash`, `fish`, `zsh`, `cmd.exe`, `PowerShell` -see [**greenlock-cli** (previously letsencrypt-cli)](https://git.coolaj86.com/coolaj86/greenlock-cli.js). - -### Now supports **Let's Encrypt v2**!! + * Install + * Simple Examples + * Example with ALL OPTIONS + * API + * Developer API + * Change History + * License Install ======= -`greenlock` requires at least two plugins: -one for managing certificate storage and the other for handling ACME challenges. - -The default storage plugin is [`le-store-certbot`](https://git.coolaj86.com/coolaj86/le-store-certbot.js) -and the default challenge is [`le-challenge-fs`](https://git.coolaj86.com/coolaj86/le-challenge-fs.js). - ```bash npm install --save greenlock@2.x - -npm install --save le-store-certbot@2.x # default plugin for accounts, certificates, and keypairs -npm install --save le-challenge-fs@2.x # default plugin for http-01 challenge -npm install --save le-challenge-sni@2.x # default plugin for tls-sni-01 and tls-sni-02 challenge -npm install --save le-acme-core@2.x # default plugin for ACME spec -npm install --save le-sni-auto@2.x # default plugin for SNICallback ``` -**Important**: Use node v4.5+ or v6.x, node <= v4.4 has a [known bug](https://github.com/nodejs/node/issues/8053) in the `Buffer` implementation. +**Note**: Ignore errors related to `ursa`. It is an optional dependency used when available. +For many people it will not install properly, but it's only necessary on ARM devices (i.e. Raspberry Pi). -Usage +Easy as 1, 2, 3... 4 ===== -It's very simple and easy to use, but also very complete and easy to extend and customize. +Greenlock is built to incredibly easy to use, without sacrificing customization or extensibility. -### Overly Simplified Example +The following examples range from just a few lines of code for getting started, +to more robust examples that you might start with for an enterprise-grade use of the ACME api. -Against my better judgement I'm providing a terribly oversimplified example -of how to use this library: +* Automatic HTTPS (for single sites) +* Fully Automatic HTTPS (for multi-domain vhosts) +* Manual HTTPS (for API integration) -```javascript -var le = require('greenlock').create({ server: 'staging' }); +Automatic HTTPS +--------------- + +**Note**: For (fully) automatic HTTPS you may prefer +the [Express.js module](https://git.coolaj86.com/coolaj86/greenlock-express.js) + +This works for most people, but it's not as fun as some of the other examples. + +Great when + + - [x] You only need a limited number of certificates + - [x] You want to use the bare node http and https modules without fluff + +```js +//////////////////// +// INIT GREENLOCK // +//////////////////// + +var path = require('path'); +var os = require('os') +var Greenlock = require('greenlock'); + +var acmeEnv = 'staging-'; +var greenlock = Greenlock.create({ + agreeTos: true // Accept Let's Encrypt v2 Agreement +, email: 'user@example.com' // IMPORTANT: Change email and domains +, approveDomains: [ 'example.com' ] +, communityMember: false // Optionally get important updates (security, api changes, etc) + // and submit stats to help make Greenlock better +, version: 'draft-11' +, server: 'https://acme-' + acmeEnv + 'v02.api.letsencrypt.org/directory' +, configDir: path.join(os.homedir(), 'acme/etc') +}); + +//////////////////// +// CREATE SERVERS // +//////////////////// + +```js +var redir = require('redirect-https')(); +require('http').createServer(greenlock.middleware(redir)).listen(80); + +require('https').createServer(greenlock.tlsOptions, function (req, res) { + res.end('Hello, Secure World!'); +}).listen(443); +``` + +Fully Automatic HTTPS +------------ + +**Note**: For (fully) automatic HTTPS you may prefer +the [Express.js module](https://git.coolaj86.com/coolaj86/greenlock-express.js) + +Great when + + - [x] You have a growing number of domains + - [x] You're integrating into your own hosting solution + - [x] Customize ACME http-01 or dns-01 challenge + +```js +//////////////////// +// INIT GREENLOCK // +//////////////////// + +var path = require('path'); +var os = require('os') +var Greenlock = require('greenlock'); + +var acmeEnv = 'staging-'; +var greenlock = Greenlock.create({ + version: 'draft-11' +, server: 'https://acme-' + acmeEnv + 'v02.api.letsencrypt.org/directory' + + // If you wish to replace the default account and domain key storage plugin +, store: require('le-store-certbot').create({ + configDir: path.join(os.homedir(), 'acme/etc') + , webrootPath: '/tmp/acme-challenges' + }) +}); + + +///////////////////// +// APPROVE DOMAINS // +///////////////////// + +var http01 = require('le-challenge-fs').create({ webrootPath: '/tmp/acme-challenges' }); +function approveDomains(opts, certs, cb) { + // This is where you check your database and associated + // email addresses with domains and agreements and such + + // Opt-in to submit stats and get important updates + opts.communityMember = true; + + // If you wish to replace the default challenge plugin, you may do so here + opts.challenges = { 'http-01': http01 }; + + // The domains being approved for the first time are listed in opts.domains + // Certs being renewed are listed in certs.altnames + if (certs) { + opts.domains = certs.altnames; + } + else { + opts.email = 'john.doe@example.com'; + opts.agreeTos = true; + } + + // NOTE: you can also change other options such as `challengeType` and `challenge` + // opts.challengeType = 'http-01'; + // opts.challenge = require('le-challenge-fs').create({}); + + cb(null, { options: opts, certs: certs }); +} + + +//////////////////// +// CREATE SERVERS // +//////////////////// + +```js +var redir = require('redirect-https')(); +require('http').createServer(greenlock.middleware(redir)).listen(80); + +require('https').createServer(greenlock.tlsOptions, function (req, res) { + res.end('Hello, Secure World!'); +}).listen(443); +``` + +Manual HTTPS +------------- + +Here's a taste of the API that you might use if building a commandline tool or API integration +that doesn't use node's SNICallback. + +``` +var staging = true; + + +///////////////////// +// SET USER PARAMS // +///////////////////// var opts = { - domains: ['example.com'], email: 'user@email.com', agreeTos: true + domains: [ 'example.com' // CHANGE EMAIL AND DOMAINS + , 'www.example.com' ] +, email: 'user@example.com' +, agreeTos: true // Accept Let's Encrypt v2 Agreement +, communityMember: true // Help make Greenlock better by submitting + // stats and getting updates }; -le.register(opts).then(function (certs) { + +//////////////////// +// INIT GREENLOCK // +//////////////////// + +var greenlock = require('greenlock').create({ + version: 'draft-11' +, server: 'https://acme-' + (staging ? 'staging-' : '') + 'v02.api.letsencrypt.org/directory' +, configDir: '/tmp/acme/etc' +}); + + +/////////////////// +// GET TLS CERTS // +/////////////////// + +greenlock.register(opts).then(function (certs) { console.log(certs); // privkey, cert, chain, expiresAt, issuedAt, subject, altnames }, function (err) { @@ -81,18 +265,17 @@ le.register(opts).then(function (certs) { }); ``` -You also need some sort of server to handle the acme challenge: +The domain key and ssl certificates you get back can be used in a webserver like this: -```javascript -var app = express(); -app.use('/', le.middleware()); +```js +var tlsOptions = { key: certs.privkey, cert: certs.cert + '\r\n' + certs.chain }; +require('https').createServer(tlsOptions, function (req, res) { + res.end('Hello, Secure World!'); +}).listen(443); ``` -Note: The `webrootPath` string is a template. -Any occurance of `:hostname` will be replaced -with the domain for which we are requested certificates. - -### Useful Example +Example with ALL OPTIONS +========= The configuration consists of 3 components: @@ -119,9 +302,6 @@ var leHttpChallenge = require('le-challenge-fs').create({ webrootPath: '~/acme/var/' // or template string such as , debug: false // '/srv/www/:hostname/.well-known/acme-challenge' }); -var leSniChallenge = require('le-challenge-sni').create({ -, debug: false -}); function leAgree(opts, agreeCb) { @@ -145,8 +325,6 @@ le = LE.create({ , store: leStore // handles saving of config, accounts, and certificates , challenges: { 'http-01': leHttpChallenge // handles /.well-known/acme-challege keys and tokens - , 'tls-sni-01': leSniChallenge // handles generating a certificate with the correct name - , 'tls-sni-02': leSniChallenge } , challengeType: 'http-01' // default to this challenge type , agreeToTerms: leAgree // hook to allow user to view and accept LE TOS @@ -283,6 +461,11 @@ See https://git.coolaj86.com/coolaj86/le-challenge-fs.js Change History ============== * v2.2 - Let's Encrypt v2 Support + * v2.2.11 - documentation updates + * v2.2.10 - don't let SNICallback swallow approveDomains errors 6286883fc2a6ebfff711a540a2e4d92f3ac2907c + * v2.2.8 - communityMember option support + * v2.2.7 - bugfix for wildcard support + * v2.2.5 - node v6.x compat * v2.2.4 - don't promisify all of `dns` * v2.2.3 - `renewWithin` default to 14 days * v2.2.2 - replace git dependency with npm @@ -307,3 +490,5 @@ LICENSE Dual-licensed MIT and Apache-2.0 See LICENSE + +Greenlock™ is a trademark of AJ ONeal diff --git a/package.json b/package.json index 64c4116..c13f160 100644 --- a/package.json +++ b/package.json @@ -20,8 +20,11 @@ "acme11", "acme-draft11", "acme-draft-11", + "auto-sni", "draft", "11", + "free ssl", + "free https", "free", "ssl", "tls", @@ -35,7 +38,7 @@ "letsencrypt2", "v2", "v02", - "greenlock", + "Greenlock", "letsencrypt.org", "le", "lejs", @@ -72,6 +75,9 @@ "pkijs": "^1.3.27", "rsa-compat": "^1.2.1" }, + "engines": { + { "node" : ">=4.5" } + }, "gitDependencies": { "acme-v2": "git+https://git.coolaj86.com/coolaj86/acme-v2.js.git#v1.0", "le-acme-core": "git+https://git.coolaj86.com/coolaj86/le-acme-core.js.git#v2.1"