2016-12-30 09:40:13 +00:00
<!-- BANNER_TPL_BEGIN -->
2016-12-30 07:53:20 +00:00
About Daplie: We're taking back the Internet!
2016-11-02 00:18:38 +00:00
--------------
2016-12-30 07:53:20 +00:00
Down with Google, Apple, and Facebook!
We're re-decentralizing the web and making it read-write again - one home cloud system at a time.
Tired of serving the Empire? Come join the Rebel Alliance:
2016-11-02 00:24:36 +00:00
2016-12-30 07:53:20 +00:00
< a href = "mailto:jobs@daplie.com" > jobs@daplie.com</ a > | [Invest in Daplie on Wefunder ](https://daplie.com/invest/ ) | [Pre-order Cloud ](https://daplie.com/preorder/ ), The World's First Home Server for Everyone
2016-11-02 00:24:36 +00:00
2016-12-30 09:40:13 +00:00
<!-- BANNER_TPL_END -->
2016-11-02 00:18:38 +00:00
2017-01-14 20:48:44 +00:00
greenlock (node-letsencrypt)
2017-01-11 23:07:49 +00:00
=========
2016-11-02 00:18:38 +00:00
2016-04-22 18:11:58 +00:00
[![Join the chat at https://gitter.im/Daplie/letsencrypt-express ](https://badges.gitter.im/Daplie/letsencrypt-express.svg )](https://gitter.im/Daplie/letsencrypt-express?utm_source=badge& utm_medium=badge& utm_campaign=pr-badge& utm_content=badge)
2017-01-11 23:07:49 +00:00
| **greenlock**
| [greenlock-cli ](https://git.daplie.com/Daplie/greenlock-cli )
| [greenlock-express ](https://git.daplie.com/Daplie/greenlock-express )
| [greenlock-cluster ](https://git.daplie.com/Daplie/greenlock-cluster )
| [greenlock-koa ](https://git.daplie.com/Daplie/greenlock-koa )
| [greenlock-hapi ](https://git.daplie.com/Daplie/greenlock-hapi )
2016-04-22 18:17:54 +00:00
|
2017-01-11 23:07:49 +00:00
Automatic [Let's Encrypt ](https://letsencrypt.org ) (ACME) HTTPS / TLS / SSL Certificates for node.js
2015-12-11 11:23:47 +00:00
2016-09-15 20:31:41 +00:00
Free SSL with [90-day ](https://letsencrypt.org/2015/11/09/why-90-days.html ) HTTPS / TLS Certificates
2015-12-13 09:04:44 +00:00
2016-08-09 23:17:22 +00:00
Are these the droids you're looking for?
------
2016-04-18 17:01:35 +00:00
2016-08-05 07:03:27 +00:00
This is a **low-level library** for implementing ACME / LetsEncrypt Clients, CLIs,
2016-04-18 17:01:35 +00:00
system tools, and abstracting storage backends (file vs db, etc).
2016-08-05 07:03:27 +00:00
2016-08-05 07:20:19 +00:00
For `express` , raw `https` or `spdy` , or `restify` (same as raw https) see
2016-08-16 20:32:35 +00:00
[**letsencrypt-express** ](https://github.com/Daplie/letsencrypt-express ) and [letsencrypt-cluster ](https://github.com/Daplie/letsencrypt-cluster ).
2016-04-18 17:01:35 +00:00
2016-08-05 07:20:19 +00:00
For `hapi` see [letsencrypt-hapi ](https://github.com/Daplie/letsencrypt-hapi ).
2016-04-18 17:27:55 +00:00
2016-08-05 07:20:19 +00:00
For `koa` or `rill`
see [letsencrypt-koa ](https://github.com/Daplie/letsencrypt-koa ).
2016-04-18 17:01:35 +00:00
2016-08-05 07:20:19 +00:00
For `bash` , `fish` , `zsh` , `cmd.exe` , `PowerShell`
see [**letsencrypt-cli** ](https://github.com/Daplie/letsencrypt-cli ).
2016-04-18 17:26:15 +00:00
2015-12-12 13:11:05 +00:00
Install
2016-08-09 23:17:22 +00:00
=======
2015-12-12 13:11:05 +00:00
2017-01-25 21:08:20 +00:00
`greenlock` requires at least two plugins:
2016-08-05 07:20:19 +00:00
one for managing certificate storage and the other for handling ACME challenges.
The default storage plugin is [`le-store-certbot` ](https://github.com/Daplie/le-store-certbot )
2016-08-09 18:05:47 +00:00
and the default challenge is [`le-challenge-fs` ](https://github.com/Daplie/le-challenge-fs ).
2016-08-05 07:20:19 +00:00
2015-12-12 13:11:05 +00:00
```bash
2017-01-25 21:08:20 +00:00
npm install --save greenlock@2.x
2016-08-09 23:43:46 +00:00
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 challenge handlers
npm install --save le-acme-core@2.x # default plugin for ACME spec
2016-08-11 16:43:07 +00:00
npm install --save le-sni-auto@2.x # default plugin for SNICallback
2015-12-12 13:11:05 +00:00
```
2016-08-30 14:54:19 +00:00
**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.
2015-12-13 09:04:44 +00:00
Usage
2016-08-09 23:17:22 +00:00
=====
2015-12-12 22:16:02 +00:00
2016-08-05 07:03:27 +00:00
It's very simple and easy to use, but also very complete and easy to extend and customize.
2015-12-12 22:16:02 +00:00
2016-08-05 07:03:27 +00:00
### Overly Simplified Example
2015-12-16 13:07:56 +00:00
2016-08-08 15:14:08 +00:00
Against my better judgement I'm providing a terribly oversimplified example
2016-08-05 07:03:27 +00:00
of how to use this library:
2015-12-17 10:38:46 +00:00
2015-12-13 11:09:06 +00:00
```javascript
2017-01-25 21:08:20 +00:00
var le = require('greenlock').create({ server: 'staging' });
2015-12-17 10:38:46 +00:00
2016-08-10 01:05:04 +00:00
var opts = {
2016-08-10 00:57:23 +00:00
domains: ['example.com'], email: 'user@email.com', agreeTos: true
2016-08-10 01:05:04 +00:00
};
le.register(opts).then(function (certs) {
2016-08-10 01:00:40 +00:00
console.log(certs);
2016-08-10 01:05:04 +00:00
// privkey, cert, chain, expiresAt, issuedAt, subject, altnames
2016-08-10 00:56:46 +00:00
}, function (err) {
console.error(err);
});
2016-08-05 07:20:19 +00:00
```
You also need some sort of server to handle the acme challenge:
2016-08-05 07:03:27 +00:00
2016-08-05 07:27:16 +00:00
```javascript
2016-08-05 07:20:19 +00:00
var app = express();
app.use('/', le.middleware());
```
Note: The `webrootPath` string is a template.
Any occurance of `:hostname` will be replaced
with the domain for which we are requested certificates.
2015-12-12 22:16:02 +00:00
2016-08-05 07:03:27 +00:00
### Useful Example
2015-12-12 22:16:02 +00:00
2016-08-05 07:03:27 +00:00
The configuration consists of 3 components:
* Storage Backend (search npm for projects starting with 'le-store-')
* ACME Challenge Handlers (search npm for projects starting with 'le-challenge-')
* Letsencryt Config (this is all you)
2015-12-12 13:11:05 +00:00
2015-12-13 09:04:44 +00:00
```javascript
2016-08-05 07:03:27 +00:00
'use strict';
2017-01-25 21:08:20 +00:00
var LE = require('greenlock');
2016-08-05 07:03:27 +00:00
var le;
2015-12-12 15:38:14 +00:00
2015-12-12 22:06:36 +00:00
2016-08-05 07:03:27 +00:00
// Storage Backend
var leStore = require('le-store-certbot').create({
2017-01-25 21:08:20 +00:00
configDir: '~/greenlock/etc' // or /etc/greenlock or wherever
2016-08-05 07:03:27 +00:00
, debug: false
});
2015-12-12 22:06:36 +00:00
2016-08-05 07:03:27 +00:00
// ACME Challenge Handlers
2016-08-09 18:05:47 +00:00
var leChallenge = require('le-challenge-fs').create({
2017-01-25 21:08:20 +00:00
webrootPath: '~/greenlock/var/' // or template string such as
2016-08-05 07:03:27 +00:00
, debug: false // '/srv/www/:hostname/.well-known/acme-challenge'
});
2015-12-12 22:06:36 +00:00
2016-08-05 07:03:27 +00:00
function leAgree(opts, agreeCb) {
// opts = { email, domains, tosUrl }
agreeCb(null, opts.tosUrl);
2015-12-12 22:06:36 +00:00
}
2015-12-12 13:11:05 +00:00
2016-08-05 07:03:27 +00:00
le = LE.create({
server: LE.stagingServerUrl // or LE.productionServerUrl
, store: leStore // handles saving of config, accounts, and certificates
2016-08-15 21:33:26 +00:00
, challenges: { 'http-01': leChallenge } // handles /.well-known/acme-challege keys and tokens
, challengeType: 'http-01' // default to this challenge type
2016-08-05 07:03:27 +00:00
, agreeToTerms: leAgree // hook to allow user to view and accept LE TOS
2016-08-15 21:39:21 +00:00
//, sni: require('le-sni-auto').create({}) // handles sni callback
2016-08-05 07:03:27 +00:00
, debug: false
2016-09-21 23:47:47 +00:00
//, log: function (debug) {console.log.apply(console, args);} // handles debug outputs
2016-08-05 07:03:27 +00:00
});
2015-12-13 01:04:12 +00:00
2015-12-12 13:11:05 +00:00
2016-08-05 07:03:27 +00:00
// If using express you should use the middleware
// app.use('/', le.middleware());
//
2016-08-09 20:12:16 +00:00
// Otherwise you should see the test file for usage of this:
2016-08-15 21:33:26 +00:00
// le.challenges['http-01'].get(opts.domain, key, val, done)
2015-12-12 13:11:05 +00:00
2016-08-05 07:03:27 +00:00
// Check in-memory cache of certificates for the named domain
2016-08-09 20:12:16 +00:00
le.check({ domains: [ 'example.com' ] }).then(function (results) {
2016-08-05 07:03:27 +00:00
if (results) {
// we already have certificates
return;
}
2015-12-12 22:06:36 +00:00
2016-08-05 22:21:10 +00:00
2016-08-05 07:03:27 +00:00
// Register Certificate manually
2016-08-09 20:12:16 +00:00
le.register({
2016-08-05 22:21:10 +00:00
domains: ['example.com'] // CHANGE TO YOUR DOMAIN (list for SANS)
, email: 'user@email.com' // CHANGE TO YOUR EMAIL
2016-08-06 05:34:34 +00:00
, agreeTos: '' // set to tosUrl string (or true) to pre-approve (and skip agreeToTerms)
2016-08-05 22:21:10 +00:00
, rsaKeySize: 2048 // 2048 or higher
, challengeType: 'http-01' // http-01, tls-sni-01, or dns-01
}).then(function (results) {
console.log('success');
}, function (err) {
// Note: you must either use le.middleware() with express,
2016-08-15 21:33:26 +00:00
// manually use le.challenges['http-01'].get(opts, domain, key, val, done)
2016-08-05 22:21:10 +00:00
// or have a webserver running and responding
// to /.well-known/acme-challenge at `webrootPath`
2017-01-25 21:08:20 +00:00
console.error('[Error]: node-greenlock/examples/standalone');
2016-08-05 22:21:10 +00:00
console.error(err.stack);
});
2015-12-12 22:06:36 +00:00
2016-08-05 07:03:27 +00:00
});
2015-12-12 13:11:05 +00:00
```
2016-08-05 07:03:27 +00:00
Here's what `results` looks like:
2015-12-12 22:06:36 +00:00
```javascript
2016-08-05 07:03:27 +00:00
{ privkey: '' // PEM encoded private key
, cert: '' // PEM encoded cert
, chain: '' // PEM encoded intermediate cert
, issuedAt: 0 // notBefore date (in ms) parsed from cert
, expiresAt: 0 // notAfter date (in ms) parsed from cert
2016-08-10 01:05:04 +00:00
, subject: '' // example.com
, altnames: [] // example.com,www.example.com
2016-08-05 07:03:27 +00:00
}
2015-12-12 13:11:05 +00:00
```
2016-08-05 07:03:27 +00:00
API
---
2015-12-12 22:06:36 +00:00
2016-08-05 07:03:27 +00:00
The full end-user API is exposed in the example above and includes all relevant options.
2015-12-12 22:06:36 +00:00
2016-08-06 05:34:34 +00:00
```
2016-08-10 01:03:34 +00:00
le.register(opts)
le.check(opts)
2016-08-06 05:34:34 +00:00
```
2016-08-05 07:03:27 +00:00
### Helper Functions
2015-12-12 13:11:05 +00:00
2016-08-05 07:03:27 +00:00
We do expose a few helper functions:
2015-12-12 22:06:36 +00:00
2016-08-05 07:03:27 +00:00
* LE.validDomain(hostname) // returns '' or the hostname string if it's a valid ascii or punycode domain name
2015-12-12 22:06:36 +00:00
2016-08-05 07:03:27 +00:00
TODO fetch domain tld list
2015-12-12 22:06:36 +00:00
2016-08-05 08:13:58 +00:00
### Template Strings
The following variables will be tempalted in any strings passed to the options object:
* `~/` replaced with `os.homedir()` i.e. `/Users/aj`
2016-08-08 22:10:23 +00:00
* `:hostname` replaced with the first domain in the list i.e. `example.com`
2016-08-05 08:13:58 +00:00
2016-08-05 07:03:27 +00:00
Developer API
-------------
2015-12-12 22:06:36 +00:00
2016-08-05 07:03:27 +00:00
If you are developing an `le-store-*` or `le-challenge-*` plugin you need to be aware of
additional internal API expectations.
2015-12-12 22:06:36 +00:00
2016-08-05 07:03:27 +00:00
**IMPORTANT**:
2015-12-12 22:06:36 +00:00
2016-08-05 07:03:27 +00:00
Use `v2.0.0` as your initial version - NOT v0.1.0 and NOT v1.0.0 and NOT v3.0.0.
2017-01-25 21:08:20 +00:00
This is to indicate that your module is compatible with v2.x of node-greenlock.
2015-12-13 05:03:48 +00:00
2017-01-25 21:08:20 +00:00
Since the public API for your module is defined by node-greenlock the major version
2016-08-05 07:03:27 +00:00
should be kept in sync.
2015-12-13 05:03:48 +00:00
2016-08-05 07:03:27 +00:00
### store implementation
2015-12-12 13:11:05 +00:00
2016-08-12 21:25:59 +00:00
See < https: / / github . com / Daplie / le-store-SPEC >
2016-08-09 20:40:35 +00:00
* getOptions()
* accounts.
* checkKeypair(opts, cb)
* check(opts, cb)
* setKeypair(opts, keypair, cb)
* set(opts, reg, cb)
* certificates.
* checkKeypair(opts, cb)
* check(opts, cb)
* setKeypair(opts, keypair, cb)
* set(opts, reg, cb)
2016-08-05 07:03:27 +00:00
### challenge implementation
2015-12-12 13:11:05 +00:00
2016-08-09 20:40:35 +00:00
See https://github.com/Daplie/le-challenge-fs
2015-12-12 13:11:05 +00:00
2016-08-09 20:40:35 +00:00
* `.set(opts, domain, key, value, cb);` // opts will be saved with domain/key
* `.get(opts, domain, key, cb);` // opts will be retrieved by domain/key
* `.remove(opts, domain, key, cb);` // opts will be retrieved by domain/key
2015-12-12 13:11:05 +00:00
2015-12-13 11:09:06 +00:00
Change History
==============
2016-08-09 20:40:35 +00:00
* v2.0.2 - Aug 9th 2016 update readme
* v2.0.1 - Aug 9th 2016
2016-08-05 07:03:27 +00:00
* major refactor
* simplified API
2016-09-24 03:18:34 +00:00
* modular plugins
2016-08-05 07:03:27 +00:00
* knock out bugs
2016-08-04 03:13:40 +00:00
* v1.5.0 now using letiny-core v2.0.0 and rsa-compat
2016-04-18 17:01:35 +00:00
* v1.4.x I can't remember... but it's better!
2015-12-16 09:19:08 +00:00
* v1.1.0 Added letiny-core, removed node-letsencrypt-python
* v1.0.2 Works with node-letsencrypt-python
* v1.0.0 Thar be dragons
2015-12-13 11:09:06 +00:00
2015-12-11 11:23:47 +00:00
LICENSE
=======
Dual-licensed MIT and Apache-2.0
See LICENSE