diff --git a/README.md b/README.md
index e88be6b..a57316f 100644
--- a/README.md
+++ b/README.md
@@ -1,466 +1,260 @@
-# Greenlock v3 on its way (Nov 1st, 2019)
-
-Greenlock v3 is in private beta (for backers) and will be available publicly by Nov 1st.
-
-You can keep an eye for updates on the [campaign page](https://indiegogo.com/at/greenlock) and,
-if this has been a useful project that's saved you time, [please contribute](https://paypal.me/rootprojects/99).
+# [Greenlock Express](https://git.rootprojects.org/root/greenlock-express.js) is Let's Encrypt for Node
![Greenlock Logo](https://git.rootprojects.org/root/greenlock.js/raw/branch/master/logo/greenlock-1063x250.png "Greenlock Logo")
-!["Greenlock Function"](https://git.rootprojects.org/root/greenlock.js/raw/branch/master/logo/from-not-secure-to-secure-url-bar.png "from url bar showing not secure to url bar showing secure")
+| Built by [Root](https://therootcompany.com) for [Hub](https://rootprojects.org/hub/)
-
-
+Free SSL, Automated HTTPS / HTTP2, served with Node via Express, Koa, hapi, etc.
-# [Greenlock](https://git.rootprojects.org/root/greenlock-express.js)™ for Express.js | a [Root](https://rootprojects.org) project
+```js
+require("greenlock-express")
+ .init(getConfig)
+ .serve(worker);
-formerly letsencrypt-express
+function getConfig() {
+ return {
+ package: require("./package.json")
+ };
+}
-Free SSL, Free Wildcard SSL, and Fully Automated HTTPS made dead simple
-certificates issued by Let's Encrypt v2 via [ACME](https://git.rootprojects.org/root/acme-v2.js)
+function worker(server) {
+ server.serveApp(function(req, res) {
+ // Works with any Node app (Express, etc)
+ res.end("Hello, Encrypted World!");
+ });
+}
+```
-!["Lifetime Downloads"](https://img.shields.io/npm/dt/greenlock.svg "Lifetime Download Count can't be shown")
-!["Monthly Downloads"](https://img.shields.io/npm/dm/greenlock.svg "Monthly Download Count can't be shown")
-!["Weekly Downloads"](https://img.shields.io/npm/dw/greenlock.svg "Weekly Download Count can't be shown")
-!["Stackoverflow Questions"](https://img.shields.io/stackexchange/stackoverflow/t/greenlock.svg "S.O. Question count can't be shown")
-
+# Let's Encrypt for...
-[Greenlock™](https://git.rootprojects.org/root/greenlock.js) is for
-[Web Servers](https://git.rootprojects.org/root/greenlock-cli.js),
-[Web Browsers](https://greenlock.domains),
-and **node.js middleware systems**.
+- IoT
+- Enterprise On-Prem
+- Local Development
+- Home Servers
+- Quitting Heroku
# Features
-- [x] Automatic HTTPS
+- [x] Let's Encrypt v2 (November 2019)
+ - [x] ACME Protocol (RFC 8555)
+ - [x] HTTP Validation (HTTP-01)
+ - [x] DNS Validation (DNS-01)
+ - [ ] ALPN Validation (TLS-ALPN-01)
+ - Need ALPN validation? [contact us](mailto:greenlock-support@therootcompany.com)
+- [x] Automated HTTPS
+ - [x] Fully Automatic Renewals every 45 days
- [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
- - [x] ACME draft 11
- - [x] Let's Encrypt v2
- - [x] Let's Encrypt v1
-- [x] Full node.js support
- - [x] node v6+
- - [x] core https module
- - [x] Express.js
- - [x] [Koa](https://git.rootprojects.org/root/greenlock-koa.js)
- - [x] [hapi](https://git.rootprojects.org/root/greenlock-hapi.js)
-- [x] Extensible Plugin Support
- - [x] AWS (S3, Route53)
- - [x] Azure
- - [x] CloudFlare
- - [x] Consul
- - [x] Digital Ocean
- - [x] etcd
- - [x] Redis
+ - [x] **Wildcard** SSL
+ - [x] **Localhost** certificates
+ - [x] HTTPS-enabled Secure **WebSockets** (`wss://`)
+- [x] Fully customizable
+ - [x] **Reasonable defaults**
+ - [x] Domain Management
+ - [x] Key and Certificate Management
+ - [x] ACME Challenge Plugins
-# Install
+# Plenty of Examples
+
+- [greenlock-express.js/examples/](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples)
+ - [Express](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/express.js)
+ - [Node's **http2**](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/http2.js)
+ - [Node's https](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/https.js)
+ - [**WebSockets**](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/websockets.js)
+ - [Socket.IO](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/socket-io.js)
+ - [Cluster](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/socket-io.js)
+ - [**Wildcards**](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/wildcards/README.md)
+ - [**Localhost**](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/localhost/README.md)
+ - [**CI/CD**](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/ci-cd/README.md)
+
+# Easy to Customize
+
+
+
+- [greenlock.js/examples/](https://git.rootprojects.org/root/greenlock.js/src/branch/master/examples)
+ - [Custom Domain Management](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/custom-manager/README.md)
+ - [Custom Key & Cert Storage](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/custom-store/README.md)
+ - [Custom ACME Challenges](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/custom-acme-challenges/README.md)
+
+# QuickStart Guide
+
+Easy as 1, 2, 3... 4
+
+## 1. Create a node project
+
+Create an empty node project.
+
+Be sure to fill out the package name, version, and an author email.
```bash
-npm install --save greenlock-express@2.x
+mkdir ~/my-project
+pushd ~/my-project
+npm init
```
-# QuickStart
+## 2. Create an http app (i.e. express)
-
+This example is shown with Express, but any node app will doGreenlock
+works with everything.
+(or any node-style http app)
-### Screencast
-
-Watch the QuickStart demonstration: [https://youtu.be/e8vaR4CEZ5s](https://youtu.be/e8vaR4CEZ5s&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk)
-
-
-
-- [0:00](https://www.youtube.com/watch?v=e8vaR4CEZ5s&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk#t=0) - Intro
-- [2:22](https://www.youtube.com/watch?v=e8vaR4CEZ5s&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk#t=142) - Demonstrating QuickStart Example
-- [6:37](https://www.youtube.com/watch?v=e8vaR4CEZ5s&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk?t=397) - Troubleshooting / Gotchas
-
-#### Beyond the QuickStart (Part 2)
-
-- [1:00](https://www.youtube.com/watch?v=bTEn93gxY50&index=2&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk&t=60) - Bringing Greenlock into an Existing Express Project
-- [2:26](https://www.youtube.com/watch?v=bTEn93gxY50&index=2&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk&t=146) - The `approveDomains` callback
-
-#### Security Concerns (Part 3)
-
-- [0:00](https://www.youtube.com/watch?v=aZgVqPzoZTY&index=3&list=PLZaEVINf2Bq_lrS-OOzTUJB4q3HxarlXk) - Potential Attacks, and Mitigation
-
-### Working Example Code
-
-Here's a completely working example that will get you started.
-
-```
-git clone https://git.rootprojects.org/root/greenlock-express.js.git
-pushd greenlock-express.js
- npm install
-popd
-
-# edit 'email' and 'approveDomains' in
-# greenlock-express.js/examples/simple.js
-
-node greenlock-express.js/examples/simple.js
-```
-
-All you have to do is start the webserver and then visit it at its domain name.
-
-`server.js`:
-
-```javascript
-"use strict";
-
-require("greenlock-express")
- .create({
- email: "john.doe@example.com", // The email address of the ACME user / hosting provider
- agreeTos: true, // You must accept the ToS as the host which handles the certs
- configDir: "~/.config/acme/", // Writable directory where certs will be saved
- communityMember: true, // Join the community to get notified of important updates
- telemetry: true, // Contribute telemetry data to the project
-
- // Using your express app:
- // simply export it as-is, then include it here
- app: require("./app.js")
-
- //, debug: true
- })
- .listen(80, 443);
-```
-
-`app.js`:
+`my-express-app.js`:
```js
"use strict";
+// A plain, node-style app
+
+function myPlainNodeHttpApp(req, res) {
+ res.end("Hello, Encrypted World!");
+}
+
+// Wrap that plain app in express,
+// because that's what you're used to
+
var express = require("express");
var app = express();
+app.get("/", myPlainNodeHttpApp);
-app.use("/", function(req, res) {
- res.setHeader("Content-Type", "text/html; charset=utf-8");
- res.end("Hello, World!\n\nš š.js");
-});
+// export the app normally
+// do not .listen()
-// Don't do this:
-// app.listen(3000)
-
-// Do this instead:
module.exports = app;
```
-### `communityMember`
+## 3. Serve with Greenlock Express
-If you're the kind of person that likes the kinds of stuff that I do,
-well, I want to do more of it and I'd like to get you involved.
+Greenlock Express is designed with these goals in mind:
-As expected, by default we keep your email private and only use it for
-transactional messaging, urgent security or API updates
-(such as the mandatory upgrade to Let's Encrypt v2), and ACME account registration.
+- Simplicity and ease-of-use
+- Performance and scalability
+- Configurability and control
-However, when you set the `communityMember` option to `true` we'll also
-inform you when there are meaningful and relavant feature updates (no bugfix noise),
-and give you early access to similar projects.
+You can start with **near-zero configuration** and
+slowly add options for greater performance and customization
+later, if you need them.
-You can see our full privacy policy at .
+`server.js`:
-### What if the example didn't work?
+```bash
+require("greenlock-express")
+ .init(getConfig)
+ .serve(worker);
-Double check the following:
+function getConfig() {
+ return {
+ // uses name and version as part of the ACME client user-agent
+ // uses author as the contact for support notices
+ package: require("./package.json")
+ };
+}
-- **Public Facing IP** for `http-01` challenges
- - Are you running this _as_ a public-facing webserver (good)? or localhost (bad)?
- - Does `ifconfig` show a public address (good)? or a private one - 10.x, 192.168.x, etc (bad)?
- - If you're on a non-public server, are you using the `dns-01` challenge?
-- **correct ACME version**
- - Let's Encrypt **v2** (ACME v2) must use `version: 'draft-11'`
- - Let's Encrypt v1 must use `version: 'v01'`
-- **valid email**
- - You MUST set `email` to a **valid address**
- - MX records must validate (`dig MX example.com` for `'john@example.com'`)
-- **valid DNS records**
- - Must have public DNS records (test with `dig +trace A example.com; dig +trace www.example.com` for `[ 'example.com', 'www.example.com' ]`)
-- **write access**
- - You MUST set `configDir` to a writeable location (test with `touch ~/acme/etc/tmp.tmp`)
-- **port binding privileges**
- - You MUST be able to bind to ports 80 and 443
- - You can do this via `sudo` or [`setcap`](https://gist.github.com/firstdoit/6389682)
-- **API limits**
- - You MUST NOT exceed the API [**usage limits**](https://letsencrypt.org/docs/staging-environment/) per domain, certificate, IP address, etc
-- **Red Lock, Untrusted**
- - You MUST use the **production** server url, not staging
- - The API URL should not have 'acme-staging-v02', but should have 'acme-v02'
- - Delete the `configDir` used for getting certificates in staging
-
-### Production vs Staging
-
-If at first you don't succeed, stop and switch to staging.
-
-There are a number of common problems related to system configuration -
-firewalls, ports, permissions, etc - that you are likely to run up against
-when using greenlock for your first time.
-
-I've put a "dry run" in place with built-in diagnostics, so hopefully
-you get everything right on your first or second try.
-
-However, in order to avoid being blocked by hitting the bad request rate limits
-you should switch to using the `staging` server for any testing or debugging.
-
-```
-https://acme-staging-v02.api.letsencrypt.org/directory
-```
-
-## Working Examples
-
-| Example | Location + Description |
-| :-------------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------: |
-| **QuickStart** | [examples/quickstart.js](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/quickstart.js) uses the fewest options and accepts all default settings. It's guaranteed to work for you. |
-| Production | [examples/production.js](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/production.js) shows how to require an express app (or other middleware system), expand the `approveDomains` callback, provides an example database shim, and exposes the server instance. |
-| Virtual Hosting | [examples/vhost.js](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/vhost.js) shows how to dynamically secure and serve domains based on their existance on the file system. |
-| Wildcard Domains | [examples/wildcard.js](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/wildcard.js) shows how to use the `acme-dns-01-cli` and wildcard cetificates. |
-| HTTPS (raw) | [examples/spdy.js](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/spdy.js) demonstrates how to manually configure a node web server using the node's built-in `http` and `https` modules. |
-| HTTP2 (spdy) | Presently spdy is incompatible with node v11, but [examples/spdy.js](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/spdy.js) demonstrates how to manually configure a node web server with spdy-compatible versions of node and Greenlock. |
-| HTTP2 (node) | [examples/http2.js](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/http2.js) uses node's new HTTP2 module, which is NOT compatible with the existing middleware systems (and is not "stable" as of v10.0). |
-| WebSockets (ws) | [examples/websockets.js](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/websockets.js) demonstrates how to use Greenlock express with a websocket server. |
-| socket.io | [examples/socket.io.js](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/socket.io.js) demonstrates how to use Greenlock express with socket.io (even though `ws` is far simpler, faster, and better and every way). |
-| - | Build Your Own
Be sure to tell me ([@solderjs](https://twitter.com/@solderjs)) / us ([@GreenlockHTTPS](https://twitter.com/@GreenlockHTTPS)) about it. :) |
-| Full List | Check out the [examples/](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples) directory |
-
-# Plugins
-
-Plugins developed by `root` are officially maintained, written in Vanilla JS, and typically have 0 dependencies.
-
-**IMPORTANT**:
-Community plugins may or may not be maintained and working.
-Please try with the defaults before switching to community plugins.
-
-## HTTP-01 Challenges
-
-Plugins for ACME / Let's Encrypt HTTP-01 Challenges.
-
-| | Plugin |
-| :--------------: | :---------------------------------------------------------------------------------------------------------------------------------------------------------------: |
-| **Default (fs)** | [root/acme-http-01-fs](https://git.rootprojects.org/root/acme-http-01-webroot.js) |
-| **Manual (cli)** | [root/acme-http-01-cli](https://git.rootprojects.org/root/acme-http-01-cli.js) |
-| standalone | [root/acme-http-01-standalone](https://git.rootprojects.org/root/acme-http-01-standalone.js) |
-| AWS S3 | [root/acme-http-01-s3](https://git.rootprojects.org/root/acme-http-01-s3.js) |
-| Azure | [kolarcz/node-le-challenge-azure-storage](https://github.com/kolarcz/node-le-challenge-azure-storage) |
-| - | Build Your Own
[acme-http-01-test](https://git.rootprojects.org/root/acme-http-01-test.js) |
-| Full List | Search [acme-http-01-](https://www.npmjs.com/search?q=acme-http-01-) on npm (or [le-challenge-](https://www.npmjs.com/search?q=le-challenge-) for older versions) |
-
-## DNS-01 Challenges
-
-Plugins for ACME / Let's Encrypt DNS-01 Challenges.
-
-| | Plugin |
-| :--------------: | :----------------------------------------------------------------------------------------------------------------------------------------: |
-| **Manual (cli)** | [root/acme-dns-01-cli](https://git.rootprojects.org/root/acme-dns-01-cli.js) |
-| Cloudflare | [nodecraft/acme-dns-01-cloudflare](https://github.com/nodecraft/acme-dns-01-cloudflare) |
-| DNSimple | [root/acme-dns-01-dnsimple](https://git.rootprojects.org/root/acme-dns-01-dnsimple.js) |
-| Digital Ocean | [root/acme-dns-01-digitalocean](https://git.rootprojects.org/root/acme-dns-01-digitalocean.js) |
-| Duck DNS | [root/acme-dns-01-duckdns](https://git.rootprojects.org/root/acme-dns-01-duckdns.js) |
-| Gandi | [root/acme-dns-01-gandi](https://git.rootprojects.org/root/acme-dns-01-gandi.js) |
-| GoDaddy | [root/acme-dns-01-godaddy](https://git.rootprojects.org/root/acme-dns-01-godaddy.js) |
-| NameCheap | [root/acme-dns-01-namecheap](https://git.rootprojects.org/root/acme-dns-01-namecheap.js) |
-| Name.com | [root/acme-dns-01-namedotcom](https://git.rootprojects.org/root/acme-dns-01-namedotcom.js) |
-| Route 53 (AWS) | [hgezim/acme-dsns-01-route53](https://github.com/hgezim/acme-dns-01-route53) |
-| Vultr | [root/acme-dns-01-vultr](https://git.rootprojects.org/root/acme-dns-01-vultr.js) |
-| etcd | [ceecko/le-challenge-etcd](https://github.com/ceecko/le-challenge-etcd) |
-| - | **Build Your Own**
[acme-dns-01-test](https://git.rootprojects.org/root/acme-dns-01-test.js) |
-| Full List | Search [acme-dns-01-](https://www.npmjs.com/search?q=acme-dns-01-) or [le-challenge-](https://www.npmjs.com/search?q=le-challenge-) on npm |
-
-## Account & Certificate Storage
-
-| | Plugin |
-| :------------------: | :---------------------------------------------------------------------------------------------------: |
-| **Simplest** | [greenlock-store-fs](https://git.rootprojects.org/root/greenlock-store-fs.js) |
-| certbot (v2 default) | [le-store-certbot](https://git.coolaj86.com/coolaj86/le-store-certbot.js) |
-| AWS S3 | [gl-store-s3](https://git.rootprojects.org/root/gl-store-s3.js) |
-| Consul | [sebastian-software/le-store-consul](https://github.com/sebastian-software/le-store-consul) |
-| json (fs) | [paulgrove/le-store-simple-fs](https://github.com/paulgrove/le-store-simple-fs) |
-| Redis | [digitalbazaar/le-store-redis](https://github.com/digitalbazaar/le-store-redis) |
-| - | Build Your Own
[greenlock-store-test](https://git.rootprojects.org/root/greenlock-store-test.js) |
-| Full List | Search [le-store-](https://www.npmjs.com/search?q=le-store-) on npm |
-
-## Auto-SNI
-
-| | Plugin |
-| :---------: | :-------------------------------------------------------------: |
-| **Default** | [le-sni-auto](https://git.coolaj86.com/coolaj86/le-sni-auto.js) |
-
-(you probably wouldn't need or want to replace this)
-
-**Bugs**: Please report bugs with the community plugins to the appropriate owner first, then here if you don't get a response.
-
-# Usage
-
-The oversimplified example was the bait
-(because everyone seems to want an example that fits in 3 lines, even if it's terribly bad practices),
-now here's the switch.
-
-We have another completely working example that will provides a little more to build off of.
-
-```
-git clone https://git.rootprojects.org/root/greenlock-express.js.git
-pushd greenlock-express.js
- npm install
-popd
-
-# replace 'fooCheckDb' in
-# greenlock-express.js/examples/normal.js
-
-node greenlock-express.js/examples/normal.js
-```
-
-It looks a little more like this:
-
-`serve.js`:
-
-```javascript
-"use strict";
-
-// returns an instance of greenlock.js with additional helper methods
-var glx = require("greenlock-express").create({
- server: "https://acme-v02.api.letsencrypt.org/directory",
- // Note: If at first you don't succeed, stop and switch to staging:
- // https://acme-staging-v02.api.letsencrypt.org/directory
- version: "draft-11", // Let's Encrypt v2 (ACME v2)
-
- // If you wish to replace the default account and domain key storage plugin
- store: require("le-store-certbot").create({
- configDir: require("path").join(require("os").homedir(), "acme", "etc"),
- webrootPath: "/tmp/acme-challenges"
- }),
-
- // Contribute telemetry data to the project
- telemetry: true,
-
- // the default servername to use when the client doesn't specify
- // (because some IoT devices don't support servername indication)
- servername: "example.com",
-
- approveDomains: approveDomains
-});
-
-var server = glx.listen(80, 443, function() {
- console.log("Listening on port 80 for ACME challenges and 443 for express app.");
-});
-```
-
-Note: You shouldn't be using the plain HTTP server for anything except, potentially, for error handling
-on the listen event (if the default print-and-quit behavior doesn't work for your use case).
-If you need to do that, here's how:
-
-```
-var plainServer = server.unencrypted;
-plainServer.on('error', function (err) { ... });
-```
-
-The Automatic Certificate Issuance is initiated via SNI (`httpsOptions.SNICallback`).
-For security, domain validation MUST have an approval callback in _production_.
-
-```javascript
-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
- // if (!isAllowed(opts.domains)) { return cb(new Error("not allowed")); }
-
- // The domains being approved for the first time are listed in opts.domains
- // Certs being renewed are listed in certs.altnames (if that's useful)
-
- // 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 };
-
- 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 });
+function worker(server) {
+ // Works with any Node app (Express, etc)
+ var app = require('my-express-app.js');
+ server.serveApp(app);
}
```
-```javascript
-// handles acme-challenge and redirects to https
-require("http")
- .createServer(glx.middleware(require("redirect-https")()))
- .listen(80, function() {
- console.log("Listening for ACME http-01 challenges on", this.address());
- });
+And start your server:
-var app = require("express")();
-app.use("/", function(req, res) {
- res.end("Hello, World!");
-});
-
-// handles your app
-require("https")
- .createServer(glx.httpsOptions, app)
- .listen(443, function() {
- console.log("Listening for ACME tls-sni-01 challenges and serve app on", this.address());
- });
+```bash
+# Allow non-root node to use ports 80 (HTTP) and 443 (HTTPS)
+sudo setcap 'cap_net_bind_service=+ep' $(which node)
```
-**Security**:
+```bash
+# `npm start` will call `node ./server.js` by default
+npm start
+```
-Greenlock will do a self-check on all domain registrations
-to prevent you from hitting rate limits.
+```txt
+Greenlock v3.0.0
+Greenlock Manager Config File: ~/.config/greenlock/manager.json
+Greenlock Storage Directory: ~/.config/greenlock/
-# API
+Listening on 0.0.0.0:80 for ACME challenges and HTTPS redirects
+Listening on 0.0.0.0:443 for secure traffic
+```
-This module is an elaborate ruse (to provide an oversimplified example and to nab some SEO).
+## 4. Manage domains
-The API is actually located at [greenlock.js options](https://git.rootprojects.org/root/greenlock.js)
-(because all options are simply passed through to `greenlock.js` proper without modification).
+Management can be done via the **CLI** or the JavaScript [**API**](https://git.rootprojects.org/root/greenlock.js/).
+Since this is the QuickStart, we'll demo the **CLI**:
-The only "API" consists of two options, the rest is just a wrapper around `greenlock.js` to take LOC from 15 to 5:
+You need to create a Let's Encrypt _subscriber account_, which can be done globally, or per-site.
+All individuals, and most businesses, should set this globally:
-- `opts.app` An express app in the format `function (req, res) { ... }` (no `next`).
-- `server = glx.listen(plainAddr, tlsAddr, onListen)` Accepts port numbers (or arrays of port numbers) to listen on, returns secure server.
- - `listen(80, 443)`
- - `listen(80, 443, onListenSecure)`
- - `listen(80, 443, onListenPlain, onListenSecure)`
- - `listen('localhost:80', '0.0.0.0:443')`
- - `listen('[::1]:80', '[::]:443')`
- - `listen('/tmp/glx.plain.sock', '/tmp/glx.secure.sock')`
+```bash
+# Set a global subscriber account
+npx greenlock config --subscriber-email 'mycompany@example.com' --agree-to-terms true
+```
-Brief overview of some simple options for `greenlock.js`:
+
-- `opts.server` set to https://acme-v02.api.letsencrypt.org/directory in production
-- `opts.version` set to `v01` for Let's Encrypt v1 or `draft-11` for Let's Encrypt v2 (mistakenly called ACME v2)
-- `opts.email` The default email to use to accept agreements.
-- `opts.agreeTos` When set to `true`, this always accepts the LetsEncrypt TOS. When a string it checks the agreement url first.
-- `opts.communityMember` Join the community to get notified of important updates and help make greenlock better
-- `opts.approveDomains` can be either of:
- - An explicit array of allowed domains such as `[ 'example.com', 'www.example.com' ]`
- - A callback `function (opts, certs, cb) { cb(null, { options: opts, certs: certs }); }` for setting `email`, `agreeTos`, `domains`, etc (as shown in usage example above)
-- `opts.renewWithin` is the **maximum** number of days (in ms) before expiration to renew a certificate.
-- `opts.renewBy` is the **minimum** number of days (in ms) before expiration to renew a certificate.
+A Let's Encrypt SSL certificate has a "Subject" (Primary Domain) and up to 100 "Alternative Names"
+(of which the first _must_ be the subject).
-## Supported ACME versions
+```bash
+# Add a certificate with specific domains
+npx greenlock add --subject example.com --altnames example.com,www.example.com
+```
-- Let's Encrypt v1 (aka v01)
-- Let's Encrypt v2 (aka v02 or ACME draft 11)
-- ACME draft 11 (ACME v2 is a misnomer)
-- Wildcard domains (via dns-01 challenges)
- - `*.example.com`
+
-tags: letsencrypt acme free ssl automated https node express.js
+This will update the config file (assuming the default fs-based management plugin):
+
+`~/.config/greenlock/manager.json`:
+
+```json
+{
+ "subscriberEmail": "letsencrypt-test@therootcompany.com",
+ "agreeToTerms": true,
+ "sites": {
+ "example.com": {
+ "subject": "example.com",
+ "altnames": ["example.com", "www.example.com"]
+ }
+ }
+}
+```
+
+Note: **Localhost**, **Wildcard**, and Certificates for Private Networks require
+[**DNS validation**](https://git.rootprojects.org/root/greenlock-exp).
+
+- DNS Validation
+ - [**Wildcards**](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/wildcards/README.md)
+ - [**Localhost**](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/localhost/README.md)
+ - [**CI/CD**](https://git.rootprojects.org/root/greenlock-express.js/src/branch/master/examples/ci-cd/README.md)
+
+# Full Documentation
+
+
+
+Most of the documentation is done by use-case examples, as shown up at the top of the README.
+
+We're working on more comprehensive documentation for this newly released version.
+**Please open an issue** with questions in the meantime.
+
+# Commercial Support
+
+Do you need...
+
+- training?
+- specific features?
+- different integrations?
+- bugfixes, on _your_ timeline?
+- custom code, built by experts?
+- commercial support and licensing?
+
+You're welcome to [contact us](mailto:aj@therootcompany.com) in regards to IoT, On-Prem,
+Enterprise, and Internal installations, integrations, and deployments.
+
+We have both commercial support and commercial licensing available.
+
+We also offer consulting for all-things-ACME and Let's Encrypt.
# Legal & Rules of the Road