Skip to content

Commit

Permalink
✨ Nginx Service
Browse files Browse the repository at this point in the history
  • Loading branch information
acburdine committed Feb 28, 2017
1 parent fc77b06 commit 3c1ae4d
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 2 deletions.
6 changes: 6 additions & 0 deletions lib/commands/service.js
@@ -1,5 +1,11 @@
'use strict';
const Config = require('../utils/config');
const checkValidInstall = require('../utils/check-valid-install');

module.exports.execute = function execute(command, args) {
checkValidInstall('service');

this.service.setConfig(Config.load(this.environment));

return this.service.callCommand(command, args);
};
4 changes: 4 additions & 0 deletions lib/services/base.js
Expand Up @@ -18,6 +18,10 @@ class BaseService {
}

command(name, fn) {
if (typeof fn !== 'function') {
fn = this[fn];
}

this.serviceManager.registerCommand(name, fn, this.name);
}

Expand Down
5 changes: 3 additions & 2 deletions lib/services/index.js
Expand Up @@ -82,7 +82,7 @@ class ServiceManager {
let command = this.commands[name];
let service = this.services[command[0]];

return Promise.resolve(service[command[1]].apply(service, args));
return Promise.resolve(command[1].apply(service, args));
}

setConfig(config, force) {
Expand Down Expand Up @@ -169,7 +169,8 @@ ServiceManager.knownServices = [
// TODO: we only know about the nginx & built in process manager services
// for now, in the future make this load globally installed services
require('./process/systemd'),
localService
localService,
require('./nginx')
];

module.exports = ServiceManager;
126 changes: 126 additions & 0 deletions lib/services/nginx/index.js
@@ -0,0 +1,126 @@
'use strict';
const fs = require('fs-extra');
const url = require('url');
const path = require('path');
const execa = require('execa');
const validator = require('validator');
const Promise = require('bluebird');
const NginxConfFile = require('nginx-conf').NginxConfFile;

const BaseService = require('../base');

class NginxService extends BaseService {
init() {
this.on('setup', 'setup');
this.command('nginx-conf', 'setupConf');
this.command('nginx-ssl', 'setupSSL');
// TODO implement
// this.command('ssl-renew', 'renewSSL');
}

get parsedUrl() {
return url.parse(this.config.get('url'));
}

setup(context) {
// This is the result from the `ghost doctor setup` command - it will be false
// if nginx does not exist on the system
if (!context.nginx) {
return;
}

if (this.parsedUrl.port) {
this.ui.log('Your url contains a port. Skipping automatic nginx setup.', 'yellow');
return;
}

if (this.parsedUrl.pathname !== '/') {
this.ui.log('The Nginx service does not support subdirectory configurations yet. Skipping automatic nginx setup.', 'yellow');
return;
}

let prompts = [{
type: 'confirm',
name: 'ssl',
message: 'Do you want to set up your blog with SSL (using letsencrypt)?',
default: true
}, {
type: 'input',
name: 'email',
message: 'Enter your email (used for ssl registration)',
when: ans => ans.ssl,
validate: email => validator.isEmail(email) || 'Invalid email'
}];

if (this.config.environment === 'development') {
prompts.splice(1, 0, {
type: 'confirm',
name: 'staging',
message: 'You are running in development mode. Would you like to use letsencrypt\'s' +
' staging servers instead of the production servers?',
default: true,
when: ans => ans.ssl
});
}

let answers;
let ghostExec = process.argv.slice(0,2).join(' ');

return this.ui.prompt(prompts).then((_answers) => {
answers = _answers;

return this.ui.noSpin(execa.shell(`sudo ${ghostExec} service nginx-conf${!answers.ssl ? ' no-ssl' : ''}`, {stdio: 'inherit'}));
}).then(() => {
if (answers.ssl) {
return this.ui.noSpin(execa.shell(`sudo ${ghostExec} service nginx-ssl ${answers.email}${answers.staging ? ' staging' : ''}`, {
stdio: 'inherit'
}));
}
});
}

setupConf(ssl) {
let isSSL = (!ssl || ssl !== 'no-ssl');
let confFile = `${this.parsedUrl.hostname}.conf`;
let confFilePath = `/etc/nginx/sites-available/${confFile}`;

fs.ensureFileSync(confFilePath);
fs.ensureSymlinkSync(confFilePath, `/etc/nginx/sites-enabled/${confFile}`);

return Promise.fromNode((cb) => NginxConfFile.create(confFilePath, cb)).then((conf) => {
conf.nginx._add('server');
conf.nginx.server._add('listen', '80');
conf.nginx.server._add('listen', '[::]:80');
conf.nginx.server._add('server_name', this.parsedUrl.hostname);

let rootPath = path.resolve(process.cwd(), 'root');
fs.ensureDirSync(rootPath);
conf.nginx.server._add('root', rootPath);

conf.nginx.server._add('location', '/');
this._addProxyBlock(conf.nginx.server.location);

if (isSSL) {
conf.nginx.server._add('location', '~ /.well-known');
conf.nginx.server.location[1]._add('allow', 'all');
}
}).then(() => {
return execa.shell('service nginx restart', {stdio: 'inherit'});
});
}

setupSSL(/* email, staging */) {

}

_addProxyBlock(location) {
location._add('proxy_set_header', 'X-Real-IP $remote_addr');
location._add('proxy_set_header', 'Host $http_host');
location._add('proxy_pass', `http://127.0.0.1:${this.config.get('server.port')}`);
}
};

module.exports = {
name: 'nginx',
class: NginxService
};
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -50,6 +50,7 @@
"knex-migrator": "2.0.7",
"listr": "0.11.0",
"lodash": "4.17.4",
"nginx-conf": "1.3.0",
"ora": "1.1.0",
"portfinder": "1.0.13",
"rxjs": "5.2.0",
Expand Down
4 changes: 4 additions & 0 deletions yarn.lock
Expand Up @@ -2139,6 +2139,10 @@ ncp@~2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3"

nginx-conf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/nginx-conf/-/nginx-conf-1.3.0.tgz#c41058a87cf7bd7eebcb91b35832a5ad53595904"

node-emoji@^1.0.4:
version "1.5.1"
resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.5.1.tgz#fd918e412769bf8c448051238233840b2aff16a1"
Expand Down

0 comments on commit 3c1ae4d

Please sign in to comment.