prepare for v3
This commit is contained in:
parent
216384e096
commit
4e447ec9cd
27
README.md
27
README.md
|
@ -57,7 +57,7 @@ greenlock --email jon@example.com \
|
|||
Robust configurations for Greenlock as a system service
|
||||
|
||||
```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.
|
||||
|
@ -95,7 +95,7 @@ These commands are shown using the **testing 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
|
||||
multiple domains doesn't work for you, file a bug.
|
||||
|
@ -111,8 +111,9 @@ greenlock certonly \
|
|||
--agree-tos --email john.doe@example.com \
|
||||
--standalone \
|
||||
--domains example.com,www.example.com \
|
||||
--server https://acme-staging.api.letsencrypt.org/directory \
|
||||
--config-dir ~/letsencrypt/etc
|
||||
--server https://acme-staging-v02.api.letsencrypt.org/directory \
|
||||
--acme-version draft-11
|
||||
--config-dir ~/acme/etc
|
||||
```
|
||||
|
||||
or
|
||||
|
@ -122,8 +123,9 @@ greenlock certonly \
|
|||
--agree-tos --email john.doe@example.com \
|
||||
--standalone --tls-sni-01-port 443 \
|
||||
--domains example.com,www.example.com \
|
||||
--server https://acme-staging.api.letsencrypt.org/directory \
|
||||
--config-dir ~/letsencrypt/etc
|
||||
--server https://acme-staging-v02.api.letsencrypt.org/directory \
|
||||
--acme-version draft-11
|
||||
--config-dir ~/acme/etc
|
||||
```
|
||||
|
||||
Then you can see your certs at `~/letsencrypt/etc/live`.
|
||||
|
@ -150,7 +152,8 @@ sudo greenlock certonly \
|
|||
--webroot --webroot-path /srv/www/example.com \
|
||||
--config-dir /etc/letsencrypt \
|
||||
--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`
|
||||
|
@ -181,9 +184,10 @@ The process works something like this. You would run:
|
|||
sudo greenlock certonly \
|
||||
--agree-tos --email john.doe@example.com \
|
||||
--hooks --hooks-server apache2-debian \
|
||||
--config-dir /etc/letsencrypt \
|
||||
--config-dir /etc/acme \
|
||||
--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:
|
||||
|
@ -239,9 +243,10 @@ will be printed to the screen and you will be given time to copy it wherever
|
|||
sudo greenlock certonly \
|
||||
--agree-tos --email john.doe@example.com \
|
||||
--manual
|
||||
--config-dir /etc/letsencrypt \
|
||||
--config-dir /etc/acme \
|
||||
--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
|
||||
|
|
|
@ -5,42 +5,46 @@ var cli = require('cli');
|
|||
var mkdirp = require('mkdirp');
|
||||
|
||||
cli.parse({
|
||||
server: [ false, " ACME Directory Resource URI.", 'string', '' ]
|
||||
, email: [ false, " Email used for registration and recovery contact. (default: null)", 'email' ]
|
||||
, 'agree-tos': [ false, " Agree to the Let's Encrypt Subscriber Agreement", 'boolean', false ]
|
||||
, domains: [ false, " Domain names to apply. For multiple domains you can enter a comma separated list of domains as a parameter. (default: [])", 'string' ]
|
||||
, 'renew-within': [ false, " Renew certificates this many days before expiry", 'int', 7 ]
|
||||
, duplicate: [ false, " Allow getting a certificate that duplicates an existing one/is an early renewal", 'boolean', false ]
|
||||
, 'rsa-key-size': [ false, " Size (in bits) of the RSA key.", 'int', 2048 ]
|
||||
, 'cert-path': [ false, " Path to where new cert.pem is saved", 'string',':configDir/live/:hostname/cert.pem' ]
|
||||
, 'fullchain-path': [ false, " Path to where new fullchain.pem (cert + chain) is saved", 'string', ':configDir/live/:hostname/fullchain.pem' ]
|
||||
, 'chain-path': [ false, " Path to where new chain.pem is saved", 'string', ':configDir/live/:hostname/chain.pem' ]
|
||||
, 'domain-key-path': [ false, " Path to privkey.pem to use for domain (default: generate new)", 'string' ]
|
||||
, 'account-key-path': [ false, " Path to privkey.pem to use for account (default: generate new)", 'string' ]
|
||||
, 'config-dir': [ false, " Configuration directory.", 'string', '~/letsencrypt/etc/' ]
|
||||
, 'tls-sni-01-port': [ false, " Use TLS-SNI-01 challenge type with this port (only port 443 is valid with most production servers)", 'int' ]
|
||||
, 'http-01-port': [ false, " Use HTTP-01 challenge type with this port (only port 80 is valid with most production servers) (default: 80)", 'int' ]
|
||||
, 'dns-01': [ false, " Use DNS-01 challange type", 'boolean', false ]
|
||||
, standalone: [ 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 ]
|
||||
, webroot: [ false, " Obtain certs by placing files in a webroot directory.", 'boolean', false ]
|
||||
, 'webroot-path': [ false, " public_html / webroot path.", 'string' ]
|
||||
, hooks: [ false, " Obtain certs with hooks that configure a webserver to meet TLS-SNI-01 challenges.", 'boolean', false ]
|
||||
, 'hooks-path': [ false, " Path in which to store files for hooks.", 'string' ]
|
||||
, 'hooks-server': [ false, " Type of webserver to configure.", 'string' ]
|
||||
, 'hooks-template': [ false, " Template to use for hooks configuration file.", 'string' ]
|
||||
, 'hooks-bind': [ false, " IP address to use in configuration for hooks.", 'string' ]
|
||||
, 'hooks-port': [ false, " Port to use in configuration for hooks.", 'string' ]
|
||||
, 'hooks-webroot': [ false, " Webroot to use in configuration for hooks (e.g. empty dir).", 'string' ]
|
||||
, 'hooks-pre-enable': [ false, " Hook to check the webserver configuration prior to enabling.", 'string' ]
|
||||
, 'hooks-enable': [ false, " Hook to enable the webserver configuration.", 'string' ]
|
||||
, 'hooks-pre-reload': [ false, " Hook to check the webserver configuration prior to reloading.", 'string' ]
|
||||
, 'hooks-reload': [ false, " Hook to reload the webserver.", 'string' ]
|
||||
, 'hooks-disable': [ false, " Hook to disable the webserver configuration.", 'string' ]
|
||||
//, 'standalone-supported-challenges': [ false, " Supported challenges, order preferences are randomly chosen. (default: http-01,tls-sni-01)", 'string', 'http-01,tls-sni-01']
|
||||
, debug: [ false, " show traces and logs", 'boolean', false ]
|
||||
, 'work-dir': [ false, "(ignored)", 'string', '~/letsencrypt/var/lib/' ]
|
||||
, 'logs-dir': [ false, "(ignored)", 'string', '~/letsencrypt/var/log/' ]
|
||||
'acme-version':
|
||||
[ 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', '' ]
|
||||
, config:
|
||||
[ 'c', " Path to configuration file --config /etc/greenlock/greenlock.yml (default: '')", 'string' ]
|
||||
, serve:
|
||||
[ false, " Run as webserver (default: false)", 'boolean', false ]
|
||||
, email:
|
||||
[ false, " Email used for registration and recovery contact (default: '')", 'email', '' ]
|
||||
, analytics:
|
||||
[ false, " Share analytics with greenlock (default: false)", 'boolean', false ]
|
||||
, community:
|
||||
[ 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 ]
|
||||
, domains:
|
||||
[ false, " Comma-separated list of domains to secure (default: [])", 'string' ]
|
||||
, 'config-dir':
|
||||
[ false, " Configuration directory.", 'string', '~/acme/etc/' ]
|
||||
, 'cert-path':
|
||||
[ 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' ]
|
||||
, 'chain-path':
|
||||
[ 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' ]
|
||||
, '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' ]
|
||||
, 'renew-within':
|
||||
[ false, " Renew certificates this many days before expiry", 'int', 11 ]
|
||||
, standalone:
|
||||
[ 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
|
||||
|
|
|
@ -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'
|
|
@ -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'
|
|
@ -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
|
2
index.js
2
index.js
|
@ -86,7 +86,7 @@ module.exports.run = function (args) {
|
|||
if (args.tlsSni01Port) {
|
||||
servers.startServers(
|
||||
[], args.tlsSni01Port
|
||||
, { debug: args.debug, httpsOptions: le.httpsOptions }
|
||||
, { debug: args.debug, tlsOptions: le.tlsOptions }
|
||||
);
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
};
|
|
@ -25,7 +25,7 @@ module.exports.create = function (challenge) {
|
|||
, startServers: function (plainPorts, tlsPorts, opts) {
|
||||
opts = opts || {};
|
||||
|
||||
var httpsOptions = opts.httpsOptions || require('localhost.daplie.me-certificates');
|
||||
var tlsOptions = opts.tlsOptions;
|
||||
var https = require('https');
|
||||
var http = require('http');
|
||||
|
||||
|
@ -56,7 +56,7 @@ module.exports.create = function (challenge) {
|
|||
|
||||
// tls-sni-01-port
|
||||
tlsPorts.forEach(function (port) {
|
||||
var server = https.createServer(httpsOptions, servers.httpResponder);
|
||||
var server = https.createServer(tlsOptions, servers.httpResponder);
|
||||
|
||||
servers._servers.push(server);
|
||||
server.listen(port, function () {
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
"le-challenge-sni": "^2.0.0",
|
||||
"le-challenge-standalone": "^2.0.0",
|
||||
"le-store-certbot": "^2.0.2",
|
||||
"localhost.daplie.me-certificates": "^1.3.2",
|
||||
"mkdirp": "^0.5.1"
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue