prepare for v3

This commit is contained in:
AJ ONeal 2018-05-12 22:55:05 -06:00
parent 216384e096
commit 4e447ec9cd
9 changed files with 226 additions and 51 deletions

View File

@ -57,7 +57,7 @@ greenlock --email jon@example.com \
Robust configurations for Greenlock as a system service Robust configurations for Greenlock as a system service
```bash ```bash
sudo greenlock --install systemd --conf /etc/greenlock/greenlock.yml sudo greenlock --install systemd --config /etc/greenlock/greenlock.yml
``` ```
See explanations below in the **Usage** section. See explanations below in the **Usage** section.
@ -95,7 +95,7 @@ These commands are shown using the **testing server**.
Want to use the **live server**? Want to use the **live server**?
1. change server to `--server https://acme-v01.api.letsencrypt.org/directory` 1. change server to `--server https://acme-v02.api.letsencrypt.org/directory`
**Note**: This has really only been tested with single domains so if **Note**: This has really only been tested with single domains so if
multiple domains doesn't work for you, file a bug. multiple domains doesn't work for you, file a bug.
@ -111,8 +111,9 @@ greenlock certonly \
--agree-tos --email john.doe@example.com \ --agree-tos --email john.doe@example.com \
--standalone \ --standalone \
--domains example.com,www.example.com \ --domains example.com,www.example.com \
--server https://acme-staging.api.letsencrypt.org/directory \ --server https://acme-staging-v02.api.letsencrypt.org/directory \
--config-dir ~/letsencrypt/etc --acme-version draft-11
--config-dir ~/acme/etc
``` ```
or or
@ -122,8 +123,9 @@ greenlock certonly \
--agree-tos --email john.doe@example.com \ --agree-tos --email john.doe@example.com \
--standalone --tls-sni-01-port 443 \ --standalone --tls-sni-01-port 443 \
--domains example.com,www.example.com \ --domains example.com,www.example.com \
--server https://acme-staging.api.letsencrypt.org/directory \ --server https://acme-staging-v02.api.letsencrypt.org/directory \
--config-dir ~/letsencrypt/etc --acme-version draft-11
--config-dir ~/acme/etc
``` ```
Then you can see your certs at `~/letsencrypt/etc/live`. Then you can see your certs at `~/letsencrypt/etc/live`.
@ -150,7 +152,8 @@ sudo greenlock certonly \
--webroot --webroot-path /srv/www/example.com \ --webroot --webroot-path /srv/www/example.com \
--config-dir /etc/letsencrypt \ --config-dir /etc/letsencrypt \
--domains example.com,www.example.com \ --domains example.com,www.example.com \
--server https://acme-staging.api.letsencrypt.org/directory --server https://acme-staging-v02.api.letsencrypt.org/directory
--acme-version draft-11
``` ```
Note that we use `sudo` because in this example we are using `/etc/letsencrypt` Note that we use `sudo` because in this example we are using `/etc/letsencrypt`
@ -181,9 +184,10 @@ The process works something like this. You would run:
sudo greenlock certonly \ sudo greenlock certonly \
--agree-tos --email john.doe@example.com \ --agree-tos --email john.doe@example.com \
--hooks --hooks-server apache2-debian \ --hooks --hooks-server apache2-debian \
--config-dir /etc/letsencrypt \ --config-dir /etc/acme \
--domains example.com,www.example.com \ --domains example.com,www.example.com \
--server https://acme-staging.api.letsencrypt.org/directory --server https://acme-staging-v02.api.letsencrypt.org/directory
--acme-version draft-11
``` ```
Three files are then generated: Three files are then generated:
@ -239,9 +243,10 @@ will be printed to the screen and you will be given time to copy it wherever
sudo greenlock certonly \ sudo greenlock certonly \
--agree-tos --email john.doe@example.com \ --agree-tos --email john.doe@example.com \
--manual --manual
--config-dir /etc/letsencrypt \ --config-dir /etc/acme \
--domains example.com,www.example.com \ --domains example.com,www.example.com \
--server https://acme-staging.api.letsencrypt.org/directory --server https://acme-staging-v02.api.letsencrypt.org/directory
--acme-version draft-11
``` ```
## Test with a free domain ## Test with a free domain

View File

@ -5,42 +5,46 @@ var cli = require('cli');
var mkdirp = require('mkdirp'); var mkdirp = require('mkdirp');
cli.parse({ cli.parse({
server: [ false, " ACME Directory Resource URI.", 'string', '' ] 'acme-version':
, email: [ false, " Email used for registration and recovery contact. (default: null)", 'email' ] [ false, " v01 (Let's Encrypt v01) or draft-11 (Let's Encrypt v02) (default: draft-11)", 'string', 'draft-11' ]
, 'agree-tos': [ false, " Agree to the Let's Encrypt Subscriber Agreement", 'boolean', false ] , 'acme-url':
, domains: [ false, " Domain names to apply. For multiple domains you can enter a comma separated list of domains as a parameter. (default: [])", 'string' ] [ false, " ACME API Directory URL (default: https://acme-v02.api.letsencrypt.org/directory", 'string', '' ]
, 'renew-within': [ false, " Renew certificates this many days before expiry", 'int', 7 ] , config:
, duplicate: [ false, " Allow getting a certificate that duplicates an existing one/is an early renewal", 'boolean', false ] [ 'c', " Path to configuration file --config /etc/greenlock/greenlock.yml (default: '')", 'string' ]
, 'rsa-key-size': [ false, " Size (in bits) of the RSA key.", 'int', 2048 ] , serve:
, 'cert-path': [ false, " Path to where new cert.pem is saved", 'string',':configDir/live/:hostname/cert.pem' ] [ false, " Run as webserver (default: false)", 'boolean', false ]
, 'fullchain-path': [ false, " Path to where new fullchain.pem (cert + chain) is saved", 'string', ':configDir/live/:hostname/fullchain.pem' ] , email:
, 'chain-path': [ false, " Path to where new chain.pem is saved", 'string', ':configDir/live/:hostname/chain.pem' ] [ false, " Email used for registration and recovery contact (default: '')", 'email', '' ]
, 'domain-key-path': [ false, " Path to privkey.pem to use for domain (default: generate new)", 'string' ] , analytics:
, 'account-key-path': [ false, " Path to privkey.pem to use for account (default: generate new)", 'string' ] [ false, " Share analytics with greenlock (default: false)", 'boolean', false ]
, 'config-dir': [ false, " Configuration directory.", 'string', '~/letsencrypt/etc/' ] , community:
, 'tls-sni-01-port': [ false, " Use TLS-SNI-01 challenge type with this port (only port 443 is valid with most production servers)", 'int' ] [ false, " Join the greenlock community to get important updates (default: false)", 'boolean', false ]
, 'http-01-port': [ false, " Use HTTP-01 challenge type with this port (only port 80 is valid with most production servers) (default: 80)", 'int' ] , 'agree-tos':
, 'dns-01': [ false, " Use DNS-01 challange type", 'boolean', false ] [ false, " Agree to the Let's Encrypt Subscriber Agreement", 'boolean', false ]
, standalone: [ false, " Obtain certs using a \"standalone\" webserver.", 'boolean', false ] , domains:
, 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, " Comma-separated list of domains to secure (default: [])", 'string' ]
, webroot: [ false, " Obtain certs by placing files in a webroot directory.", 'boolean', false ] , 'config-dir':
, 'webroot-path': [ false, " public_html / webroot path.", 'string' ] [ false, " Configuration directory.", 'string', '~/acme/etc/' ]
, hooks: [ false, " Obtain certs with hooks that configure a webserver to meet TLS-SNI-01 challenges.", 'boolean', false ] , 'cert-path':
, 'hooks-path': [ false, " Path in which to store files for hooks.", 'string' ] [ false, " Path where new cert.pem is saved", 'string',':configDir/live/:hostname/cert.pem' ]
, 'hooks-server': [ false, " Type of webserver to configure.", 'string' ] , 'fullchain-path':
, 'hooks-template': [ false, " Template to use for hooks configuration file.", 'string' ] [ false, " Path where new fullchain.pem (cert + chain) is saved", 'string', ':configDir/live/:hostname/fullchain.pem' ]
, 'hooks-bind': [ false, " IP address to use in configuration for hooks.", 'string' ] , 'chain-path':
, 'hooks-port': [ false, " Port to use in configuration for hooks.", 'string' ] [ false, " Path where new chain.pem is saved", 'string', ':configDir/live/:hostname/chain.pem' ]
, 'hooks-webroot': [ false, " Webroot to use in configuration for hooks (e.g. empty dir).", 'string' ] , 'bundle-path':
, 'hooks-pre-enable': [ false, " Hook to check the webserver configuration prior to enabling.", 'string' ] [ false, " Path where new bundle.pem (fullchain + privkey) is saved", 'string', ':configDir/live/:hostname/bundle.pem' ]
, 'hooks-enable': [ false, " Hook to enable the webserver configuration.", 'string' ] , 'privkey-path':
, 'hooks-pre-reload': [ false, " Hook to check the webserver configuration prior to reloading.", 'string' ] [ false, " Path where (new or existing) domain privkey.pem is saved", 'string', ':configDir/live/:hostname/privkey.pem' ]
, 'hooks-reload': [ false, " Hook to reload the webserver.", 'string' ] , 'root':
, 'hooks-disable': [ false, " Hook to disable the webserver configuration.", 'string' ] [ false, " public_html / webroot path /srv/www/:hostname", 'string' ]
//, 'standalone-supported-challenges': [ false, " Supported challenges, order preferences are randomly chosen. (default: http-01,tls-sni-01)", 'string', 'http-01,tls-sni-01'] , 'renew-within':
, debug: [ false, " show traces and logs", 'boolean', false ] [ false, " Renew certificates this many days before expiry", 'int', 11 ]
, 'work-dir': [ false, "(ignored)", 'string', '~/letsencrypt/var/lib/' ] , standalone:
, 'logs-dir': [ false, "(ignored)", 'string', '~/letsencrypt/var/log/' ] [ 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 ]
, debug:
[ false, " show traces and logs", 'boolean', false ]
}); });
// ignore certonly and extraneous arguments // ignore certonly and extraneous arguments

View File

@ -0,0 +1,45 @@
daemon: true
http_port: 80
https_port: 443
version: draft-11
server: https://acme-staging-v02.api.letsencrypt.org/directory
webroot_path: /srv/www
store:
module: 'le-store-certbot'
options:
config_dir: /etc/greenlock/
domains:
'*':
check:
module: 'fs-exists'
options:
path: /srv/www/:hostname
email: MY_EMAIL
agree_tos: MY_AGREE
analytics: true
challenges:
'https-01':
module: 'le-challenge-fs'
'example.com,www.example.com':
path: /srv/www/example.com
email: MY_EMAIL
agree_tos: MY_AGREE
analytics: true
challenges:
'dns-01':
module: 'le-challenge-cloudflare'
options:
email: 'jon@example.com'
key: 'xxxxxxxxxxxxxxxxx'
'.example.com':
check: null
path: /srv/www/example.com
email: MY_EMAIL
agree_tos: MY_AGREE
analytics: true
challenges:
'dns-01':
module: 'le-challenge-digitalocean'
options:
email: 'jon@example.com'
key: 'xxxxxxxxxxxxxxxxx'

22
dist/etc/greenlock/greenlock.yml vendored Normal file
View File

@ -0,0 +1,22 @@
daemon: true
http_port: 80
https_port: 443
version: draft-11
server: https://acme-staging-v02.api.letsencrypt.org/directory
webroot_path: /srv/www
store:
module: 'le-store-certbot'
options:
config_dir: /etc/greenlock/
domains:
'*':
email: MY_EMAIL
agree_tos: MY_AGREE
analytics: true
checks:
- module: 'greenlock-plugin-approve-fs'
options:
www: false
path: /srv/www/:hostname
challenges:
module: 'le-challenge-fs'

View File

@ -0,0 +1,69 @@
[Unit]
Description=MY_DESC
Documentation=MY_DOCS
After=network-online.target
Wants=network-online.target systemd-networkd-wait-online.service
[Service]
# Restart on crash (bad signal), and on 'clean' failure (error exit code)
# Allow up to 3 restarts within 10 seconds
# (it's unlikely that a user or properly-running script will do this)
Restart=on-failure
StartLimitInterval=10
StartLimitBurst=3
# The v8 VM will output a "clean" exit for JavaScript errors.
# If we knew we were never going to accidentally exit cleanly
# we would use on-abnormal:
; Restart=on-abnormal
# User and group the process will run as
# (www-data is the de facto standard on most systems)
User=MY_USER
Group=MY_GROUP
# If we need to pass environment variables in the future
Environment=NODE_PATH=MY_GREENLOCK_PATH/lib/node_modules NPM_CONFIG_PREFIX=MY_GREENLOCK_PATH
# Set a sane working directory, sane flags, and specify how to reload the config file
WorkingDirectory=MY_GREENLOCK_PATH
ExecStart=MY_GREENLOCK_PATH/bin/node MY_GREENLOCK_PATH/bin/greenlock --daemon --config MY_CONFIG_PATH
ExecReload=/bin/kill -USR1 $MAINPID
# Limit the number of file descriptors and processes; see `man systemd.exec` for more limit settings.
# Unmodified greenlock is not expected to use more than this.
LimitNOFILE=1048576
LimitNPROC=64
# Use private /tmp and /var/tmp, which are discarded after greenlock stops.
PrivateTmp=true
# Use a minimal /dev
PrivateDevices=true
# Hide /home, /root, and /run/user. Nobody will steal your SSH-keys.
ProtectHome=true
# Make /usr, /boot, /etc and possibly some more folders read-only.
ProtectSystem=full
# … except TLS/SSL, ACME, and Let's Encrypt certificates
# and /var/log/greenlock, because we want a place where logs can go.
# This merely retains r/w access rights, it does not add any new. Must still be writable on the host!
ReadWriteDirectories=MY_RW_DIRS
# you may also want to add other directories such as /opt/greelock /etc/acme /etc/letsencrypt
# Note: in v231 and above ReadWritePaths has been renamed to ReadWriteDirectories
; ReadWritePaths=/etc/greenlock /var/log/greenlock
# The following additional security directives only work with systemd v229 or later.
# They further retrict privileges that can be gained.
# Note that you may have to add capabilities required by any plugins in use.
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=true
# Caveat: Some plugins need additional capabilities.
# For example "upload" needs CAP_LEASE
; CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_LEASE
; AmbientCapabilities=CAP_NET_BIND_SERVICE CAP_LEASE
; NoNewPrivileges=true
[Install]
WantedBy=multi-user.target

View File

@ -86,7 +86,7 @@ module.exports.run = function (args) {
if (args.tlsSni01Port) { if (args.tlsSni01Port) {
servers.startServers( servers.startServers(
[], args.tlsSni01Port [], args.tlsSni01Port
, { debug: args.debug, httpsOptions: le.httpsOptions } , { debug: args.debug, tlsOptions: le.tlsOptions }
); );
} }
else { else {

31
lib/install-systemd.js Normal file
View File

@ -0,0 +1,31 @@
'use strict';
module.exports.install = function (opts, cb) {
var fs = require('fs');
var path = require('path');
var service = '/etc/systemd/system/greenlock.service';
var rwDirs = [ '/etc/greenlock', '/srv/www', '/var/log/greenlock', '/opt/greenlock' ];
fs.readFile(path.join(__dirname, '../dist', service), 'utf8', function (e, text) {
if (e) { throw e; }
text = text
.replace(/MY_DESC/g, opts.description || 'Greenlock Secure Web Server')
.replace(/MY_DOCS/g, opts.homepage || 'https://git.coolaj86.com/coolaj86/greenlock-cli.js')
.replace(/MY_GREENLOCK_PATH/g, opts.greenlockPath || '/opt/greenlock')
.replace(/MY_CONFIG_PATH/g, opts.greenlockPath || '/etc/greenlock/greenlock.yml')
.replace(/MY_USER/g, opts.user || 'greenlock')
.replace(/MY_GROUP/g, opts.user || 'greenlock')
.replace(/MY_RW_DIRS/g, (opts.writableDirs || rwDirs).join(' '))
;
fs.writeFile(service, text, 'utf8', function (e) {
if (e) { throw e; }
console.log("Now reload configs and enable to start on boot:");
console.log("");
console.log("\tsudo systemctl daemon-reload");
console.log("\tsudo systemctl enable greenlock");
cb(null);
});
});
};

View File

@ -25,7 +25,7 @@ module.exports.create = function (challenge) {
, startServers: function (plainPorts, tlsPorts, opts) { , startServers: function (plainPorts, tlsPorts, opts) {
opts = opts || {}; opts = opts || {};
var httpsOptions = opts.httpsOptions || require('localhost.daplie.me-certificates'); var tlsOptions = opts.tlsOptions;
var https = require('https'); var https = require('https');
var http = require('http'); var http = require('http');
@ -56,7 +56,7 @@ module.exports.create = function (challenge) {
// tls-sni-01-port // tls-sni-01-port
tlsPorts.forEach(function (port) { tlsPorts.forEach(function (port) {
var server = https.createServer(httpsOptions, servers.httpResponder); var server = https.createServer(tlsOptions, servers.httpResponder);
servers._servers.push(server); servers._servers.push(server);
server.listen(port, function () { server.listen(port, function () {

View File

@ -43,7 +43,6 @@
"le-challenge-sni": "^2.0.0", "le-challenge-sni": "^2.0.0",
"le-challenge-standalone": "^2.0.0", "le-challenge-standalone": "^2.0.0",
"le-store-certbot": "^2.0.2", "le-store-certbot": "^2.0.2",
"localhost.daplie.me-certificates": "^1.3.2",
"mkdirp": "^0.5.1" "mkdirp": "^0.5.1"
} }
} }