Compare commits

...

2 Commits

Author SHA1 Message Date
AJ ONeal 8cf13b329a making progress 2018-05-13 01:31:44 -06:00
AJ ONeal c30e25e25b standalone 2018-05-12 23:03:42 -06:00
7 changed files with 228 additions and 184 deletions

305
README.md
View File

@ -1,6 +1,6 @@
![Greenlock Logo](https://git.coolaj86.com/coolaj86/greenlock.js/raw/branch/master/logo/greenlock-1063x250.png "Greenlock Logo")
# Greenlock™ for Web Servers
# Greenlock™ Certificate Manager for Web Servers
A server-friendly commandline tool for Free SSL, Free Wildcard SSL, and Fully Automated HTTPS
<small>certificates issued by Let's Encrypt v2 via ACME</small>
@ -10,6 +10,59 @@ Greenlock is also available
[for node.js](https://git.coolaj86.com/coolaj86/greenlock-express.js),
and [for API integrations](https://git.coolaj86.com/coolaj86/greenlock.js)
Why use Greenlock? Two Reasons:
===============================
One
---
You want to be able to run a command like this:
```bash
sudo greenlock --domains example.com --config /etc/greenlock/greenlock.yml
```
And then get awesome results like this:
```
/etc/ssl/acme
├── accounts
│   └── acme-staging-v02.api.letsencrypt.org/directory
│   └── c07a31a70c691d64f6b4d31f51a6dd9c
│  ├── meta.json
│  ├── private_key.json
│  └── regr.json
└── live
   └── example.com <-- Free SSL like magic! Wow!
   ├── bundle.pem
   ├── cert.pem
   ├── chain.pem
    ├── fullchain.pem
    └── privkey.pem
```
That you use with your existing webserver - Apache, Nginx, HAProxy, node.js, etc
And install to renew so that you never worry about ssl again.
Two
---
You want to be able to run a command like this:
```bash
sudo greenlock --install systemd --config /etc/greenlock.yml --webroot '/srv/www/:hostname'
```
To immediately secure and publish any and all sites you have in a web root like this:
```
/srv/www/
├── coolsite.rocks
├── example.com
└── whatever.app
```
Features
========
@ -28,54 +81,15 @@ Features
- [x] HTTP Challenge Plugins - AWS S3, Azure, Consul, etcd
- [x] DNS Challenge Plugins - AWS Route53, CloudFlare, Digital Ocean
- [x] Account & Certificate Storage Plugins - AWS S3, Redis
Demo
====
Run as a webserver:
```bash
sudo greenlock --daemon \
--email jon@example.com \
--agree-tos \
--root /srv/www/example.com \
--domains example.com,www.example.com
```
Fetch certificates for Apache, Nginx, or HAProxy:
```bash
greenlock --email jon@example.com \
--agree-tos \
--domains example.com,www.example.com \
--webroot-path /srv/www/example.com \
--privkey-path /etc/ssl/privkey.pem \
--fullchain-path /etc/ssl/fullchain.pem \
--bundle-path /etc/ssl/bundle.pem
```
Robust configurations for Greenlock as a system service
```bash
sudo greenlock --install systemd --config /etc/greenlock/greenlock.yml
```
See explanations below in the **Usage** section.
- [x] Built-in WebServer
Install
=======
Windows
-------
1. Install node.js
2. Open `Node.js cmd.exe`
2. Run the command `npm install -g greenlock-cli`
Mac
---
Open Terminal
Open Terminal and run this install script:
```bash
curl -fsS https://get.greenlock.app/ | bash
@ -84,10 +98,111 @@ curl -fsS https://get.greenlock.app/ | bash
Linux
-----
Open Terminal and run this install script:
```bash
curl -fsS https://get.greenlock.app/ | bash
```
Windows & Node.js
-----------------
1. Install [node.js](https://nodejs.org)
2. Open _Node.js_
2. Run the command `npm install -g greenlock-cli`
Important: How to Not Get Blocked
===================
PLEASE READ ALL THREE SENTENCES:
* These examples use the PRODUCTION ENVIRONMENT (where you can be blocked)
* If an example DOESN'T WORK on the first try, STOP!
* UNCOMMENT the `--staging` flag and see the TROUBLESHOOTING SECTION
Quick Examples
==============
The most basic options are exposed as commandline flags,
just so that we can do little domes like this.
The config file is explained after the troubleshooting section.
### The Greenlock HTTPS WebServer
Easy to run on your server, nothing else required:
```bash
sudo greenlock --webserver \
--agree-tos --email jon@example.com \
--domains example.com,www.example.com \
--webroot /srv/www/example.com \
--config-dir ~/acme/etc #--staging
```
### Add SSL to an Existing WebServer
For all the Apache, Nginx, and HAProxy fans out there:
(use your existing webroot)
```bash
sudo greenlock --agree-tos --email jon@example.com \
--domains example.com,www.example.com \
--webroot /srv/www/example.com \
--privkey-path /etc/ssl/example.com/privkey.pem \
--fullchain-path /etc/ssl/example.com/fullchain.pem \
--bundle-path /etc/ssl/example.com/bundle.pem \
--config-dir /etc/ssl/acme #--staging
```
### Get SSL Certificates Interactively
Run this manual process on your laptop and copy the certificates
to you server afterwards:
```bash
greenlock --agree-tos --email jon@example.com \
--domains example.com,www.example.com \
--privkey-path /etc/ssl/example.com/privkey.pem \
--fullchain-path /etc/ssl/example.com/fullchain.pem \
--bundle-path /etc/ssl/example.com/bundle.pem \
--manual \
--config-dir /etc/ssl/acme #--staging
```
### Standalone SSL Certificate Retrieval
Run this on a server standalone just to retrieve
certificates:
```bash
sudo greenlock --agree-tos --email jon@example.com \
--domains example.com,www.example.com \
--privkey-path /etc/ssl/example.com/privkey.pem \
--fullchain-path /etc/ssl/example.com/fullchain.pem \
--bundle-path /etc/ssl/example.com/bundle.pem \
--standalone \
--config-dir ~/etc/ssl/acme #--staging
```
Troubleshooting
===============
Watch the [Troubleshooting Screencast](https://youtu.be/e8vaR4CEZ5s?t=397)
**Note**: Replace `whatever.com` with your domain, use your real email, etc.
0. Use the `--staging` flag while troubleshooting
1. Do you have a valid A record for `whatever.com`?
2. When you `ping whatever.com` do you see that same address?
3. Can you confirm that's your server's address with `ifconfig` or `ipconfig`?
4. Do you have write access to all of the directories you've specified?
**Important**: Don't forget to delete the directory specified in `--config-dir`
when you get things figured out and remove `--staging`.
Usage
=====
@ -138,7 +253,7 @@ This option is great for testing, but since it requires the use of
the same ports that your webserver needs, it isn't a good choice
for production.
### WebRoot (production option 1)
### WebRoot
You can specify the path to where you keep your `index.html` with `webroot`, as
long as your server is serving plain HTTP on port 80.
@ -168,71 +283,6 @@ ls /etc/letsencrypt/live/
You can use a cron job to run the script above every 80 days (the certificates expire after 90 days)
so that you always have fresh certificates.
### Hooks (production option 2)
You can also integrate with a secure server. This is more complicated than the
webroot option, but it allows you to obtain certificates with only port 443
open. This facility can work with any web server as long as it supports server
name indication (SNI) and you can provide a configuration file template and
shell hooks to install and uninstall the configuration (without downtime). In
fact, it doesn't even need to be a webserver (though it must run on port 443);
it could be another server that performs SSL/TLS negotiation with SNI.
The process works something like this. You would run:
```bash
sudo greenlock certonly \
--agree-tos --email john.doe@example.com \
--hooks --hooks-server apache2-debian \
--config-dir /etc/acme \
--domains example.com,www.example.com \
--server https://acme-staging-v02.api.letsencrypt.org/directory
--acme-version draft-11
```
Three files are then generated:
* a configuration fragment: `some-long-string.conf`
* a challenge-fulfilling certificate: `the-same-long-string.crt`
* a private key: `the-same-long-string.key`
A hook is then run to enable the fragment, e.g. by linking it (it should not be
moved) into a `conf.d` directory (for Apache on Debian, `sites-enabled`). A
second hook is then run to check the configuration is valid, to avoid
accidental downtime, and then another to signal to the server to reload the
configuration. The server will now serve the generated certificate on a special
domain to prove you own the domain you're getting a certificate for.
After the domain has been validated externally, hooks are run to disable the
configuration fragment, and again check and reload the configuration.
You can then find your brand new certs in:
```
ls /etc/letsencrypt/live/
```
Tailor to your server and distro using the `--hooks-server` option. So far, the
following are supported (contributions for additional servers welcome):
* apache2-debian
To tweak it for your setup and taste, see all the `hooks-` options in the
Command Line Options section below. Also note that the following substitutions
are available for use in the hooks and the template:
* `{{{token}}}`: the token
* `{{{domain}}}`: the domain for which a certificate is being sought (beware of
this if using multiple domains per certificate)
* `{{{subject}}}`: the domain for which the generated challenge-fulfilling
certificate must be used (only available when generating it)
* `{{{cert}}}`: the path to the generated certificate: `hooks-path/token.crt`
* `{{{privkey}}}`: the path to the generated private key: `hooks-path/token.key`
* `{{{conf}}}`: the path to the generated config file: `hooks-path/token.conf`
* `{{{bind}}}`: the value of the `hooks-bind` option
* `{{{port}}}`: the value of the `hooks-port` option
* `{{{webroot}}}`: the value of the `hooks-webroot` option
### Interactive (for debugging)
The token (for all challenge types) and keyAuthorization (only for https-01)
@ -310,11 +360,6 @@ Options:
--renew-within [NUMBER] Renew certificates this many days before expiry. (default: 7)
--duplicate BOOLEAN Allow getting a certificate that duplicates an existing one/is
an early renewal.
--rsa-key-size [NUMBER] Size (in bits) of the RSA key. (Default is 2048)
--cert-path STRING Path to where new cert.pem is saved
(Default is :conf/live/:hostname/cert.pem)
@ -326,13 +371,8 @@ Options:
--domain-key-path STRING Path to privkey.pem to use for domain (default: generate new)
--account-key-path STRING Path to privkey.pem to use for account (default: generate new)
--config-dir STRING Configuration directory. (Default is ~/letsencrypt/etc/)
--tls-sni-01-port NUMBER Use TLS-SNI-01 challenge type with this port.
(must be 443 with most production servers) (Boulder allows 5001 in testing mode)
--http-01-port [NUMBER] Use HTTP-01 challenge type with this port, used for SimpleHttp challenge. (Default is 80)
(must be 80 with most production servers)
@ -347,35 +387,6 @@ Options:
--webroot-path STRING public_html / webroot path.
--hooks BOOLEAN Obtain certs with hooks that configure a webserver to meet TLS-SNI-01 challenges.
--hooks-path STRING Path in which to store files for hooks.
(Default is ~/letsencrypt/apache)
--hooks-server STRING Type of webserver to configure. Sets defaults for all the following --hooks- options.
Either --hooks-server or --hooks-template must be given.
(See the Hooks section above for a list of supported servers.)
--hooks-template STRING Template to use for hooks configuration file.
Either --hooks-server or --hooks-template must be given.
--hooks-bind STRING IP address to use in configuration for hooks. (Default is *)
--hooks-port STRING Port to use in configuration for hooks. (Default is 443)
--hooks-webroot STRING Webroot to use in configuration for hooks (e.g. empty dir).
Nothing should actually be served from here. (Default is /var/www)
--hooks-pre-enable STRING Hook to check the webserver configuration prior to enabling.
--hooks-enable STRING Hook to enable the webserver configuration.
--hooks-pre-reload STRING Hook to check the webserver configuration prior to reloading.
--hooks-reload STRING Hook to reload the webserver.
--hooks-disable STRING Hook to disable the webserver configuration.
--debug BOOLEAN show traces and logs
-h, --help Display help and usage details

View File

@ -6,52 +6,75 @@ var mkdirp = require('mkdirp');
cli.parse({
'acme-version':
[ false, " v01 (Let's Encrypt v01) or draft-11 (Let's Encrypt v02) (default: draft-11)", 'string', 'draft-11' ]
[ false, " v01 (Let's Encrypt v01) or draft-11 (Let's Encrypt v02) (default: draft-11)", 'string'
, 'draft-11' ]
, 'acme-url':
[ false, " ACME API Directory URL (default: https://acme-v02.api.letsencrypt.org/directory", 'string', '' ]
[ false, " ACME API Directory URL (default: https://acme-v02.api.letsencrypt.org/directory", 'string'
, 'https://acme-staging-v02.api.letsencrypt.org/directory' ]
, 'aol-keyword-www':
[ false, " Travel back in time to 1995 where we redirect bare domains as to have a triple-w prefix", 'string'
, false ]
, config:
[ 'c', " Path to configuration file --config /etc/greenlock/greenlock.yml (default: '')", 'string' ]
, serve:
[ false, " Run as webserver (default: false)", 'boolean', false ]
[ false, " Run as webserver (default: false)", 'boolean'
, false ]
, email:
[ false, " Email used for registration and recovery contact (default: '')", 'email', '' ]
[ false, " Email used for registration and recovery contact (default: '')", 'email' ]
, analytics:
[ false, " Share analytics with greenlock (default: false)", 'boolean', false ]
[ false, " Share analytics with greenlock (default: false)", 'boolean'
, false ]
, community:
[ false, " Join the greenlock community to get important updates (default: false)", 'boolean', false ]
[ false, " Join the greenlock community to get important updates (default: false)", 'boolean'
, false ]
, 'agree-tos':
[ false, " Agree to the Let's Encrypt Subscriber Agreement", 'boolean', false ]
[ false, " Agree to the Let's Encrypt Subscriber Agreement", 'boolean'
, false ]
, domains:
[ false, " Comma-separated list of domains to secure (default: [])", 'string' ]
, 'config-dir':
[ false, " Configuration directory.", 'string', '~/acme/etc/' ]
[ false, " Configuration directory.", 'string'
, '~/acme/etc/' ]
, 'cert-path':
[ false, " Path where new cert.pem is saved", 'string',':configDir/live/:hostname/cert.pem' ]
[ false, " Path where new cert.pem is saved", 'string'
, ':configDir/live/:hostname/cert.pem' ]
, 'fullchain-path':
[ false, " Path where new fullchain.pem (cert + chain) is saved", 'string', ':configDir/live/:hostname/fullchain.pem' ]
[ false, " Path where new fullchain.pem (cert + chain) is saved", 'string'
, ':configDir/live/:hostname/fullchain.pem' ]
, 'chain-path':
[ false, " Path where new chain.pem is saved", 'string', ':configDir/live/:hostname/chain.pem' ]
[ false, " Path where new chain.pem is saved", 'string'
, ':configDir/live/:hostname/chain.pem' ]
, 'bundle-path':
[ false, " Path where new bundle.pem (fullchain + privkey) is saved", 'string', ':configDir/live/:hostname/bundle.pem' ]
[ false, " Path where new bundle.pem (fullchain + privkey) is saved", 'string'
, ':configDir/live/:hostname/bundle.pem' ]
, 'privkey-path':
[ false, " Path where (new or existing) domain privkey.pem is saved", 'string', ':configDir/live/:hostname/privkey.pem' ]
, 'root':
[ false, " public_html / webroot path /srv/www/:hostname", 'string' ]
[ false, " Path where (new or existing) domain privkey.pem is saved", 'string'
, ':configDir/live/:hostname/privkey.pem' ]
, 'webroot':
[ false, " public_html / webroot path such as /srv/www/:hostname", 'string' ]
, 'renew-within':
[ false, " Renew certificates this many days before expiry", 'int', 11 ]
[ false, " Renew certificates this many days before expiry", 'int'
, 11 ]
, staging:
[ false, " Use Let's Encrypt v02 staging API", 'boolean'
, false ]
, standalone:
[ false, " Obtain certs using a \"standalone\" webserver.", 'boolean', false ]
[ false, " Obtain certs using a \"standalone\" webserver", 'boolean'
, false ]
, manual:
[ false, " Print the token and key to the screen and wait for you to hit enter, giving you time to copy it somewhere before continuing (default: false)", 'boolean', false ]
[ false, " Print the token and key to the screen and wait for you to hit enter, giving you time to copy it somewhere before continuing (default: false)", 'boolean'
, false ]
, debug:
[ false, " show traces and logs", 'boolean', false ]
[ false, " show traces and logs", 'boolean'
, false ]
});
// ignore certonly and extraneous arguments
cli.main(function(_, options) {
console.log('');
var args = {};
var homedir = require('homedir')();
var homedir = require('os').homedir();
Object.keys(options).forEach(function (key) {
var val = options[key];

View File

@ -1,8 +0,0 @@
#!/bin/bash
node bin/letsencrypt certonly \
--agree-tos --email 'john.doe@gmail.com' \
--standalone \
--domains example.com,www.example.com \
--server https://acme-staging.api.letsencrypt.org/directory \
--config-dir ~/letsencrypt.test/etc

8
examples/server.sh Normal file
View File

@ -0,0 +1,8 @@
#!/bin/bash
greenlock \
--agree-tos --email 'john.doe@gmail.com' \
--serve
--root /root/www/example.com \
--domains example.com,www.example.com \
--config-dir ~/acme.test/etc

7
examples/standalone.sh Executable file
View File

@ -0,0 +1,7 @@
#!/bin/bash
greenlock \
--agree-tos --email 'john.doe@gmail.com' \
--standalone \
--domains example.com,www.example.com \
--config-dir ~/acme.test/etc

7
examples/webroot.sh Normal file
View File

@ -0,0 +1,7 @@
#!/bin/bash
greenlock \
--agree-tos --email 'john.doe@gmail.com' \
--root /root/www/example.com \
--domains example.com,www.example.com \
--config-dir ~/acme.test/etc

View File

@ -34,15 +34,11 @@
},
"homepage": "https://git.coolaj86.com/coolaj86/greenlock-cli.js",
"dependencies": {
"cli": "^0.11.1",
"greenlock": "^2.1.16",
"homedir": "^0.6.0",
"le-acme-core": "^2.0.5",
"le-challenge-hooks": "^2.0.0",
"le-challenge-manual": "^2.0.0",
"le-challenge-sni": "^2.0.0",
"le-challenge-standalone": "^2.0.0",
"le-store-certbot": "^2.0.2",
"cli": "^1.0.1",
"greenlock": "^2.2.11",
"le-challenge-manual": "^2.1.0",
"le-challenge-standalone": "^2.1.0",
"le-store-certbot": "^2.1.0",
"mkdirp": "^0.5.1"
}
}