Skip to content

Commit

Permalink
feat(ssl): refactor ssl setup to use acme.sh rather than greenlock
Browse files Browse the repository at this point in the history
no issue
- greenlock implicitly requires python, acme.sh is much more widely used
  • Loading branch information
acburdine committed Jul 6, 2017
1 parent b0407da commit 52cdcab
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 199 deletions.
1 change: 1 addition & 0 deletions extensions/nginx/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
acme.sh
11 changes: 9 additions & 2 deletions extensions/nginx/commands/ssl-renew.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,15 @@ class SslRenewCommand extends cli.Command {
}

let email = instance.cliConfig.get('extension.sslemail');
return this.ui.run(letsencrypt(instance, email, false), 'Renewing SSL certificate')
.catch((error) => Promise.reject(new cli.errors.ProcessError(error)));
return this.ui.run(letsencrypt(instance, email, false, true), 'Renewing SSL certificate')
.catch((error) => {
if (error.stdout.match(/Skip/)) {
this.ui.log('Certificate not due for renewal yet, skipping', 'yellow');
return;
}

return Promise.reject(new cli.errors.ProcessError(error));
});
}
}

Expand Down
6 changes: 3 additions & 3 deletions extensions/nginx/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -199,11 +199,11 @@ class NginxExtension extends cli.Extension {
https._add('listen', '[::]:443 ssl http2');
https._add('server_name', parsedUrl.hostname);

let letsencryptPath = path.join(ctx.instance.dir, 'system', 'letsencrypt', 'live');
let letsencryptPath = path.join(ctx.instance.dir, 'system', 'letsencrypt');

// add ssl cert directives
https._add('ssl_certificate', path.join(letsencryptPath, parsedUrl.hostname, 'fullchain.pem'));
https._add('ssl_certificate_key', path.join(letsencryptPath, parsedUrl.hostname, 'privkey.pem'));
https._add('ssl_certificate', path.join(letsencryptPath, 'fullchain.pem'));
https._add('ssl_certificate_key', path.join(letsencryptPath, 'privkey.pem'));
// add ssl-params snippet
https._add('include', path.join(ctx.instance.dir, 'system', 'files', 'ssl-params.conf'));
// add root directive
Expand Down
39 changes: 28 additions & 11 deletions extensions/nginx/letsencrypt.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
'use strict';
const fs = require('fs-extra');
const url = require('url');
const path = require('path');
const execa = require('execa');
const download = require('download');

const LIVE_URL = 'https://acme-v01.api.letsencrypt.org/directory';
const STAGING_URL = 'https://acme-staging.api.letsencrypt.org/directory';
// This is how we will do version control for acme.sh
const ACME_VERSION = '2.7.2';

module.exports = function letsencrypt(instance, email, staging) {
let hostname = url.parse(instance.config.get('url')).hostname;
let rootPath = path.resolve(instance.dir, 'system', 'nginx-root');
let letsencryptFolder = path.join(instance.dir, 'system', 'letsencrypt');
let sslGenArgs = `certonly --agree-tos --email ${email} --webroot --webroot-path ${rootPath}` +
` --config-dir ${letsencryptFolder} --domains ${hostname} --server ${staging ? STAGING_URL : LIVE_URL}`;
module.exports = function letsencrypt(instance, email, staging, renew) {
let downloadPromise;
let acmePath = path.join(__dirname, 'acme.sh');

return execa('greenlock', sslGenArgs.split(' '), {
preferLocal: true,
localDir: __dirname
if (fs.existsSync(acmePath)) {
downloadPromise = Promise.resolve();
} else {
let acmeUrl = `https://raw.githubusercontent.com/Neilpang/acme.sh/${ACME_VERSION}/acme.sh`;
downloadPromise = download(acmeUrl).then(data => fs.writeFile(acmePath, data, {mode: 0o774}));
}

return downloadPromise.then(() => {
let hostname = url.parse(instance.config.get('url')).hostname;
let rootPath = path.resolve(instance.dir, 'system', 'nginx-root');
let letsencryptFolder = path.join(instance.dir, 'system', 'letsencrypt');

fs.ensureDirSync(letsencryptFolder);

let fullchain = path.join(letsencryptFolder, 'fullchain.pem');
let privkey = path.join(letsencryptFolder, 'privkey.pem');

let cmd = `${acmePath} --${renew ? 'renew' : 'issue'} --domain ${hostname} --webroot ${rootPath} ` +
`--accountemail ${email} --key-file ${privkey} --fullchain-file ${fullchain}${staging ? ' --staging' : ''}`;

return execa.shell(cmd);
});
};
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
"fkill": "5.0.0",
"fs-extra": "3.0.1",
"ghost-ignition": "2.8.11",
"greenlock-cli": "2.2.9",
"inquirer": "3.1.1",
"is-running": "2.1.0",
"knex-migrator": "2.0.16",
Expand Down
Loading

0 comments on commit 52cdcab

Please sign in to comment.