|
|
@ -1,81 +1,76 @@ |
|
|
|
# greenlock-hapi |
|
|
|
# Greenlock™ for hapi |
|
|
|
|
|
|
|
(previously letsencrypt-hapi) |
|
|
|
An Automated HTTPS ACME client (Let's Encrypt v2) for hapi |
|
|
|
|
|
|
|
| [greenlock (lib)](https://git.coolaj86.com/coolaj86/greenlock.js) |
|
|
|
| [greenlock-cli](https://git.coolaj86.com/coolaj86/greenlock-cli.js) |
|
|
|
| [greenlock-express](https://git.coolaj86.com/coolaj86/greenlock-express.js) |
|
|
|
| [greenlock-cluster](https://git.coolaj86.com/coolaj86/greenlock-cluster.js) |
|
|
|
| [greenlock-koa](https://git.coolaj86.com/coolaj86/greenlock-koa.js) |
|
|
|
| **greenlock-hapi** |
|
|
|
| |
|
|
|
| Sponsered by [ppl](https://ppl.family) |
|
|
|
| Greenlock™ is for |
|
|
|
[Browsers](https://git.coolaj86.com/coolaj86/greenlock.html), |
|
|
|
[Node.js](https://git.coolaj86.com/coolaj86/greenlock.js), |
|
|
|
[Commandline](https://git.coolaj86.com/coolaj86/greenlock-cli.js), |
|
|
|
[Express.js](https://git.coolaj86.com/coolaj86/greenlock-express.js), |
|
|
|
[Node.js Cluster](https://git.coolaj86.com/coolaj86/greenlock-cluster.js), |
|
|
|
**hapi**, |
|
|
|
[Koa](https://git.coolaj86.com/coolaj86/greenlock-koa.js), |
|
|
|
and [rill](https://git.coolaj86.com/coolaj86/greenlock-rill.js) | |
|
|
|
|
|
|
|
Free SSL and Automatic HTTPS for node.js with hapi.js and other middleware systems via Let's Encrypt |
|
|
|
Features |
|
|
|
======== |
|
|
|
|
|
|
|
* Automatic Registration via SNI (`httpsOptions.SNICallback`) |
|
|
|
* **registrations** require an **approval callback** in *production* |
|
|
|
* Automatic Renewal (around 80 days) |
|
|
|
* **renewals** are *fully automatic* and happen in the *background*, with **no downtime** |
|
|
|
* Automatic vhost / virtual hosting |
|
|
|
* [x] Automatic Registration via SNI (`httpsOptions.SNICallback`) |
|
|
|
* [x] Secure domain approval callback |
|
|
|
* [x] Automatic renewal between 10 and 14 days before expiration |
|
|
|
* [x] Virtual Hosting (vhost) with Multiple Domains & SAN |
|
|
|
* [x] plugins for AWS, redis, etc |
|
|
|
* [x] and [more](https://git.coolaj86.com/coolaj86/greenlock-express.js) |
|
|
|
|
|
|
|
All you have to do is start the webserver and then visit it at it's domain name. |
|
|
|
This module is just an alias for greenlock-express.js, |
|
|
|
which works with any middleware system. |
|
|
|
|
|
|
|
## Install |
|
|
|
Install |
|
|
|
======= |
|
|
|
|
|
|
|
``` |
|
|
|
npm install --save greenlock-express@2.x |
|
|
|
npm install --save greenlock-hapi@2.x |
|
|
|
``` |
|
|
|
|
|
|
|
*Pay no attention to the man behind the curtain.* (just ignore that the name of the module is greenlock-express) |
|
|
|
|
|
|
|
### Part 1: Configure Greenlock |
|
|
|
QuickStart |
|
|
|
========== |
|
|
|
|
|
|
|
```javascript |
|
|
|
'use strict'; |
|
|
|
|
|
|
|
var le = require('greenlock-express').create({ |
|
|
|
////////////////////// |
|
|
|
// Greenlock Setup // |
|
|
|
////////////////////// |
|
|
|
|
|
|
|
var greenlock = require('greenlock-hapi').create({ |
|
|
|
version: 'draft-11' // Let's Encrypt v2 |
|
|
|
// You MUST change this to 'https://acme-v02.api.letsencrypt.org/directory' in production |
|
|
|
server: 'https://acme-staging-v02.api.letsencrypt.org/directory' |
|
|
|
, version: 'draft-11' // Let's Encrypt v2 |
|
|
|
|
|
|
|
, configDir: require('os').homedir() + '/letsencrypt/etc' |
|
|
|
|
|
|
|
, approveDomains: function (opts, certs, cb) { |
|
|
|
opts.domains = certs && certs.altnames || opts.domains; |
|
|
|
opts.email = 'john.doe@example.com' // CHANGE ME |
|
|
|
opts.agreeTos = true; |
|
|
|
|
|
|
|
cb(null, { options: opts, certs: certs }); |
|
|
|
} |
|
|
|
|
|
|
|
, debug: true |
|
|
|
}); |
|
|
|
``` |
|
|
|
, server: 'https://acme-staging-v02.api.letsencrypt.org/directory' |
|
|
|
|
|
|
|
WARNING: If you don't do any checks and simply complete `approveDomains` callback, |
|
|
|
an attacker will spoof SNI packets with bad hostnames and that will cause you to be rate-limited |
|
|
|
and/or blocked from the ACME server. |
|
|
|
Alternatively, You can run registration *manually*: |
|
|
|
, email: 'jon@example.com' |
|
|
|
, agreeTos: true |
|
|
|
, approveDomains: [ 'example.com' ] |
|
|
|
|
|
|
|
```bash |
|
|
|
npm install -g greenlock-cli |
|
|
|
// Join the community to get notified of important updates |
|
|
|
// and help make greenlock better |
|
|
|
, communityMember: true |
|
|
|
|
|
|
|
greenlock certonly --standalone \ |
|
|
|
--server 'https://acme-v02.api.letsencrypt.org/directory' \ |
|
|
|
--config-dir ~/acme/etc \ |
|
|
|
--agree-tos --domains example.com --email user@example.com |
|
|
|
, configDir: require('os').homedir() + '/acme/etc' |
|
|
|
|
|
|
|
# Note: the '--webrootPath' option is also available if you don't want to shut down your webserver to get the cert. |
|
|
|
``` |
|
|
|
//, debug: true |
|
|
|
}); |
|
|
|
|
|
|
|
### Part 2: Just add Hapi |
|
|
|
|
|
|
|
```javascript |
|
|
|
/////////////////// |
|
|
|
// Just add hapi // |
|
|
|
/////////////////// |
|
|
|
|
|
|
|
var hapi = require('hapi'); |
|
|
|
var https = require('spdy'); |
|
|
|
var https = require('https'); |
|
|
|
var server = new hapi.Server(); |
|
|
|
var acmeResponder = le.middleware(); |
|
|
|
var httpsServer = https.createServer(le.httpsOptions).listen(443); |
|
|
|
var acmeResponder = greenlock.middleware(); |
|
|
|
var httpsServer = https.createServer(greenlock.httpsOptions).listen(443); |
|
|
|
|
|
|
|
server.connection({ listener: httpsServer, autoListen: false, tls: true }); |
|
|
|
|
|
|
@ -98,15 +93,38 @@ server.route({ |
|
|
|
reply("Hello, I'm so Hapi!"); |
|
|
|
} |
|
|
|
}); |
|
|
|
``` |
|
|
|
|
|
|
|
### Part 3: Redirect http to https |
|
|
|
|
|
|
|
```javascript |
|
|
|
// |
|
|
|
// http redirect to https |
|
|
|
// |
|
|
|
var http = require('http'); |
|
|
|
var redirectHttps = require('redirect-https')(); |
|
|
|
|
|
|
|
http.createServer(le.middleware(redirectHttps)).listen(80, function () { |
|
|
|
console.log('handle ACME http-01 challenge and redirect to https'); |
|
|
|
http.createServer(greenlock.middleware(redirectHttps)).listen(80, function () { |
|
|
|
console.log('Listening on port 80 to handle ACME http-01 challenge and redirect to https'); |
|
|
|
}); |
|
|
|
``` |
|
|
|
|
|
|
|
Usage & Troubleshooting |
|
|
|
============================ |
|
|
|
|
|
|
|
See <https://git.coolaj86.com/coolaj86/greenlock-express.js> |
|
|
|
|
|
|
|
Handling a dynamic list of domains |
|
|
|
======================== |
|
|
|
|
|
|
|
In the oversimplified exapmple above we handle a static list of domains. |
|
|
|
If you add domains programmatically you'll want to use the `approveDomains` |
|
|
|
callback. |
|
|
|
|
|
|
|
**SECURITY**: Be careful with this. |
|
|
|
If you don't check that the domains being requested are the domains you |
|
|
|
allow an attacker can make you hit your rate limit for failed verification |
|
|
|
attempts. |
|
|
|
|
|
|
|
We have a |
|
|
|
[vhost example](https://git.coolaj86.com/coolaj86/greenlock-express.js/src/branch/master/examples/vhost.js) |
|
|
|
that allows any domain for which there is a folder on the filesystem in a specific location. |
|
|
|
|
|
|
|
See that example for an idea of how this is done. |
|
|
|